App design question: user_photo helper

I’m having trouble using an application helper and understanding how I
should make it work throughout my application - so if you can help me
with this I’ll be overcoming a big hurdle in my learning.

Here’s the helper method;

[code=]# application_helper.rb

def user_photo
if @user.photo?
return @user.photo.public_filename(:thumb)
else
return ‘rails.png’
end
end[/code]

Pretty simple. I understand what it does, and it works just fine in my
show action in the user controller;

[code=]# user_controller.rb

def show
@user = User.find(params[:id])
end[/code]

[code=]# show.html.erb

<%= @user.login %>

<%= image_tag user_photo %>

Email: <%= @user.email %>

Joined: <%= @user.created_at.to_s(:long) %>

Posts: <%= @user.posts.count %>

[/code]

However, I want this helper to work elsewhere in the app, such as a
_post partial, which obviously is called on the Post index and show
actions, etc. But because the user_photo method uses the @user instance
variable, I need to make it work when @user isn’t set in the current
controller, e.g. the posts index action (if I use the user_photo in the
_post partial on the post index action, I inevitably get a nil object
because @user.photo doesn’t exist);

[code=]def index
@posts = Post.list(params[:page])

respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => @posts }
end
end[/code]

I’m already pulling @posts on the post index (and there is a
‘post.user.photo’ in every ‘post’ in @posts); do I need to define the
@user instance variable in all the necessary controller actions, by
doing something like this;

[code=]def index
@posts = Post.list(params[:page])
@user = “post.user for every post in @posts” # something along those
lines…

respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => @posts }
format.rss { render :rss => @posts }
end
end[/code]

Or can I do this in a different way which doesn’t involve defining @user
in every controller action ?

why not just pass the object to your helper method as an argument?

def user_photo(user)
user.photo? ? user.photo.public_filename(:thumb) : ‘default.png’
end

then in your view template just use:

<%= user_photo(@user) %>

Mike

Thanks Mike. I’ve tried your suggestion but it doesn’t work - definitely
due to my lack of understanding. On the posts index, I get the
following;

You have a nil object when you didn’t expect it!
The error occurred while evaluating nil.photo?

I replaced the previous helper with your much more streamlined version.
I also put the <%= user_photo(@user) %> in place of <%= link_to
image_tag user_photo %> in the _post partial (I’ll put the link_to and
image_tag in when it’s all working). But the post index action isn’t
passing a @user variable (as seen in the original post, above), and the
_post partial currently works by calling ‘post.user’, or
‘post.created_at.to_s(:short)’ local variables on the @posts :collection
passed on the index view;

Latest Posts

<%= render :partial => ‘post’, :collection => @posts %>

<%= will_paginate @posts %>

How does the @user variable fit in to this? Wouldn’t it need to be
defined in either the application helper or the Posts index action?

Robin, thanks for the explanation. A user has many posts, and a post
belongs to a user. I’m still getting an error from the _post partial;

“undefined method `photo?’ for #User:0x3656eec

application_helper.rb

def user_photo(user)
user.photo? ? user.photo.public_filename(:thumb) : ‘rails.png’
end

_post.html.erb

<%= user_photo(post.user) %>

I don’t understand why I’m getting the error, because I can link to a
post.user.photo as follows;

<%= link_to image_tag(post.user.photo.public_filename(:thumb)),
user_path(post.user) %>

And that successfully passes the ‘post.user’ to the user_path. Surely
I’m misunderstanding how the helper uses the post.user to fetch the
photo…

On Feb 29, 11:55 am, Neil C. [email protected]
wrote:

How does the @user variable fit in to this? Wouldn’t it need to be
defined in either the application helper or the Posts index action?

If you want to display a photo that is associated with a user, you
will need to have access to the user object for that photo.

Looking at your original post, it appears that a post belongs to a
user - is this correct? If so, in the posts index action for example,
you would call Mike’s suggested method as user_photo(post.user). What
this is doing is passing the user object associated with that post
through to the user_photo helper.

Regards

Robin