super_J
super_J

Reputation: 234

Rails 4 passing variables in the views or templates

I have an app that will allow the owner (but not public users) to upload photo album files and photos. When coding my views, I noticed something strange.In the do block in my albums/index.html.erb file, if I pass in the variable @album.id, I get a NoMethodError for NilClass.Yet, if I remove the "@", (or remove that variable entirely), it works fine.

But in my albums/show.html.erb file, in the link_to line of code for editing an album title, I need the "@album.id" to be passed (or the variable left out entirely) in order for it to work.

Why is that?

Here is my albums/index.html.erb file and code

    <div class="admin_login"><%= link_to "Admin Login", new_album_path %></div>
    <div class="home"><%= link_to "Home", root_path %></div>

    <h1>Albums Gallery</h1>

    <% @albums.each do |album| %>
      <div>
        <%= link_to album.name, album_path(album.id) %>    
      </div>
    <% end %>

And here is my albums/show.html.erb file:

<h3><%= link_to @album.name %></h3>
<div class="album">
  <%= link_to "Edit", edit_album_path(@album.id) %>
  <%= link_to "Delete", @album, method: :delete, data:{confirm: "Are you sure you want to    delete this album? All photos in it will be permanently deleted!"} %>
</div>
<br><%= link_to "Back", albums_path %>

For clarity, here is my albums controller code:

    class AlbumsController < ApplicationController
      def index
        @albums = Album.all
      end

      def new
        @album = Album.new
      end

      def create
        @album = Album.new(album_params)
        @album.save
        redirect_to albums_path
      end

      def show
        @album = Album.find(params[:id])
      end

      def edit
        @album = Album.find(params[:id])    
      end

      def update
        @album = Album.find(params[:id])
          if @album.update(album_params)
            redirect_to album_path(@album.id)
          else
           render 'edit'
          end
      end

      def destroy
        @album = Album.find(params[:id])
        @album.destroy
        redirect_to albums_path
      end

      private

      def album_params
        params.require(:album).permit(:id, :name, :category)
      end
    end

Upvotes: 2

Views: 113

Answers (2)

gdpelican
gdpelican

Reputation: 568

In your index action, you're defining a series of albums as @albums. In your show action, you define just a single @album. These variables are accessible only in the action in which they are defined.

The reason that 'album' works in your index view is that the each block is defining a local 'album' variable within the block's scope.

<% @albums.each do |album| %>
  <div>
    <%= link_to album.name, album_path(album.id) %>    
  </div>
<% end %>

That |album| after the do block says "for this iteration, assign the current value to the variable album"

Upvotes: 1

dostu
dostu

Reputation: 1518

You need to setup instance variables in the controller. Make sure you set @albums in AlbumsController index action and @album in show action. The do block uses block variable, not instance, so there is no need for @.

Upvotes: 0

Related Questions