Hi guys,
I’m puzzled by an error I’m getting in my app.
I have some declarations in my show method:
GET /tabs/1
GET /tabs/1.xml
def show
@tab = Tab.find(params[:id])
@videos = Video.find(:all, :conditions => [“tab_id = ?”, params[:id]])
@video = @tab.videos.build
@comment = @tab.comments.build
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => @tab }
end
end
I have objects called tab. Users can add comments and videos to tabs.
From the show view I want to be able to create a video and comment. It
goes fine for the videos. That’s why the @tab.videos/comments.build are
there.
Now. As said everything is ok with the videos.
In the view I have one part with this:
<% for comment in @tab.comments.reverse %>
<%=h comment.created_by %> <%=h
comment.created_at.to_s(:short) %> <%=h comment.body %>
<% end %>
So I can simply list the comments for a tab.
But but, when I have the line @comment = @tab.comments.build in the
controller. I get the next error:
wrong number of arguments (1 for 0)
In the line:
<%=h comment.created_by %> <%=h comment.created_at.to_s(:short)
%> <%=h comment.body %>
The strange thing is that if I remove the .to_s(:short) in that line
there is no problem.
I can’t find a reason why the .to_s(:short) and @comment =
@tab.comments.build cause that.
Do you have any hints?
Thanks.
On Apr 9, 2008, at 4:21 PM, comopasta Gr wrote:
@tab = Tab.find(params[:id])
@tab.comments.build cause that.
Do you have any hints?
Thanks.
That comment has yet to be saved and thus has no created_at. Well, to
be precise, comment.created_at is nil. Now, NilClass#to_s exists, but
takes no arguments. The Time#to_s has be redefined by ActiveSupport
to take a format symbol. Your error is from a call to nil.to_s(:short)
In your view you could either test for nil? or do something like:
<%= comment.new_record? ? ‘(unsaved)’ :
comment.created_at.to_s(:short) %>
a test of comment.created_at.nil? would be an equally valid condition,
but this seems more intention-revealing.
-Rob
Rob B. http://agileconsultingllc.com
[email protected]
comopasta Gr wrote:
@comment = @tab.comments.build
At this point, @tab.comments now contains a new, uninitialised comment
with nil valued attributes (including the timestamps).
comment.created_at.to_s(:short)
One of the comments is the above mentioned uninitialised one so for this
one comment.created_at is nil which responds to #to_s but not with an
argument.
If the @comment instance variable is there for a form, then use:
@comment = Comment.new
instead.
Ok. Now your comments helped me spotting an error in my code. The point
is that in the same “show” view I can list the existing comments for
that tab and also create a new comment for the tab. Separate issues.
So I use one object to read the existing ones:
@comments = Comment.find(:all, :conditions => [“tab_id = ?”,
params[:id]])
And another to be able to create new one:
@comment = @tab.comments.build
My error was that in the view I was not using the @comments to iterate
the existing comments.
I was using: @tab.comments.reverse directly used from the view.
So, instead of using that I am now using @comments.reverse and the
errors are gone.
Thanks!
It’s probably because whatever object is being sent “to_s” isn’t the
object you think it is.
It’s probably nil, which would mean to_s would work, but to_s(:short)
won’t.
After you’ve built, created_at will be nil, which will set up the case
that I just described.
Set an initial value for it in the controller, and all will be good.
@comment = @tab.comments.build(:created_at => Time.now)
or
@comment = @tab.comments.build; @comment.created_at = Time.now
Julian.
Learn Ruby on Rails! Check out the FREE VIDS (for a limited time)
VIDEO #3 out NOW!
http://sensei.zenunit.com/