Reputation: 234
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
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
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