I am experiencing a very odd problem; I get this error
undefined method `to_datetime' for nil:NilClass"
when render 'modal' is before render 'post' in show.html.erb, but not if it is after:
<div class="page-header">
<h2>Indlæg af <%= #user.first_name %></h2>
</div>
<% if current_user == #user %>
<%= render 'modal' %>
<% end %>
<%= render 'post' %>
I have attached the views in the gist underneath:
Gist: https://gist.github.com/czepluch/8166841
It makes no sense to me that this error occurs depending on the order the renders are placed in. So I would really like to know why the order of the rendering of the helpers matter?
Please add code to the question so it is saved with the answers here. I suspect it has to do with the fact that your form has this:
simple_form_for([#user, #user.posts.build]
That means a new post is built that has no attributes, which could cause a nil error later on. reverse the order, and this isn't built until after the other code has run. The only thing I can see at first glance that is related to datetime would be:
time_ago_in_words(p.created_at)
If created_at is nil, because of an empty post, that could generate an error.
Play with the form declaration, you may be able to do
simple_form_for([#user, :post])
or something like that to get a form for a new post without actually attaching an empty object to the #user object.
Related
I'm trying to render simple check_boxes in a list of results so users can select on which of these results to get additional content for.
Example model setup (names changed):
UserRequest has_one :response
Response has_many :individual_results
IndividualResult has_one :contact_info
In the UserRequestsController I have a show action, which shows the user_request (duh), response, and its individual_results in a table.
The user should be able to select items (= contact_info) to request additional content for those. For some reason I don't manage to render the check_boxes after days of trying. Basically, I don't really understand where and how to store the array of selected contact_infos and how to pass it to the method that then gets the additional content.
My attempt was:
Create a ContactInfosController (didn't exist before, the user was only creating and showing her requests up to now, so contact_info was "model only" before)
Create a method request_content(contact_infos) (as post, to pass the user-selected contact_infos to. If I were to make it Restful, it would probably be "edit/update")
Add the form with check_boxes search_request#show
My search_request/show.html.erb:
<tbody>
<% if #response %>
<% form_for #contact_infos, url: contact_infos_request_content_path(#contact_infos) do |form| %>
<% #response.individual_results.each do |result| %>
# result.foo, ...
# result.contact_info.bar
<%= form.check_box "contact_info", "contact_info.request_content?", "true", "false %>
<% end %>
# form.submit
<% end %>
<% end %>
</tbody>
As it didn't work, I also had to declare the instance variable #contact_infos in RequestsController#show as #contact_infos = #response.individual_results.map { |r| r.contact_info }
Now, it fails at the check_box with "undefined method `merge'". Also, not sure how the params would be passed? I feel I went seriously "off the rails" and probably screwed up the design with this as it seems way too complicated...
Would anybody be so kind and help me get into the right direction, e.g., how would you pass the response to a method to request additional information? Read tons online but somehow couldn't apply it.
Thanks so much!
I'm currently going through Michael Hartl's railstutorial.org, and have run into a question that Google/Stackoverflow don't seem to be answering: The tutorial has us display user information in the view by putting <%= #user.name %>, <%= #user.email %> in show.html.erb. In the controller, it has us define a show method: #user = User.find(params[:id]).
I understand why this works, but what I don't understand is why the following code does not produce the same result (I removed the show method from the controller and tried to place all the code in the view). These are my editions to show.html.erb:
<%= #user.find(params[:id]).name %>, <%= #user.find(params[:id]).email %>
It returns "undefined method `find' for nil:NilClass".
I'm sure you understand by now from the other answers and probably the tutorial that you should not have this logic in the view, HOWEVER, to answer your question:
The reason why <%= #user.find(params[:id]).name %> generates the error
undefined method 'find' for nil:NilClass is because #user is an instance variable which you deleted from the show method in the controller. So now, #user is nil and doesn't exist. Also, when you want to query the database you must use the class (model) name which is User instead of #user.
So whiles its bad practice to do this, if you wanted to, you could do <%= User.find(params[:id]).name %> (as long as its a correct id) and that would work. Your params are available in the view as they are in the controller too.
Finally, if you intend to use the show view, you cannot completely delete the show method, you must have at least:
def show
end
in order for it to work.
params is probably not available in the view, and it shouldn't.
Your problem is the main reason why you should do your data preparation in the controller: to catch issues with the data. That's the reason a controller exists.
Your code would make two requests to the database instead of one, if it wouldn't be for rails side query caching.
Prepare your #user in the controller and access it in the view. It will make testing and refactoring your code way easier and greatly improve readability.
Compare
<%= User.find(params[:id]).name %>, <%= User.find(params[:id]).email %>
VS.
<%= #user.name %>, <%= #user.email %>
You really shouldn't have a lot of logic in the views, but I think the code you are looking for is:
<%= User.find(params[:id]).name %>, <%= User.find(params[:id]).email %>
I've been stuck on this problem for days. First off, I now know this code is horribly wrong. I've been trying to fix it, but it's way more important in the short term that this link is created. In my view (I'm so sorry), I call the create method like this, if a certain condition is met:
index.html.erb (controller: subjects_controller)
<%= Baseline.create(subject_id: sub.subject_id) %>
I do this several times on the page, from several controllers (i.e., FollowUp3Week.create(subject_id: sub.subject_id) works). All of the other controllers work. I've checked, and double checked, every controller action and compared them to each other, and they appear the same.
So instead of creating the record, it leaves something like this instead:
#<Baseline:0x007f944c4f7f80>
I'm at a bit of a trouble shooting loss. Once again, I know how wrong it is to have these database actions in the view. But I didn't know that when I made the page, and I really need this to function before I can take the time to learn how to rearrange everything through the MVC.
Any advice would be greatly appreciated. Let me know what other code you might want to look at.
EDIT 1.
link Creation:
<% if Baseline.where(subject_id: sub.subject_id).first != nil %>
<%= link_to "edit", baseline_path(Baseline.where(subject_id: sub.subject_id).first) %>
<% else %>
<%= Baseline.create(subject_id: sub.subject_id) %>
<% end %>
First of all, making DB calls in views is a big NO! NO!
Secondly, to answer why you see the output as
#<Baseline:0x007f944c4f7f80>
for
<%= Baseline.create(subject_id: sub.subject_id) %>
You are trying to render an instance of Baseline model. Its just how the instance would be displayed. If you want to display a particular attribute's value in view then just do
<%= Baseline.create(subject_id: sub.subject_id).subject_id %>
Also, this code will not create a link. To create a link you would have to call link_to helper in your view.
What you need to do is, move the Baseline.create call in the controller. Set an instance variable in the action which renders this particular view as below:
def action_name
#baseline = Baseline.create(subject_id: sub.subject_id)
end
After this in you view you can easily access all the attributes of #baseline instance.
For example:
To access subject_id
<%= #baseline.subject_id %>
To create a link for show page of #baseline, provided you have a RESTful route to show action for baselines
<%= link_to "Some Link", #baseline %>
When calling all posts for a user Posts.find(creator: current_user:_id), and the user hasn't made any...rails spits a "NoMethodError" for it...
What I want to do is have a pretty output for the user of "Why, no. You haven't posted anything, you lazy slob." instead of this scary error.
What's the best way to handle things like this?
You need to use where instead of find. By design, find method expect to actually find an existing thing you're looking for. Consult docs about querying here.
Also, you can try and use try method. Basically it's equal to the following:
object.try(:something_scary)
# is equal to
object && object.something_scary
This is how I handle nil entities. If you want to show some kind of message to user (about being slobby) you make a check inside of your template and render different partials. Example:
<% if #posts.present? %>
<%= render 'posts' %>
<% else %>
<%= render 'no_posts' %>
<% end %>
Then you can put your message inside of that no_posts partial.
I'm trying to pass in the variable "post" to a partial. The partial is being used on both my show#view & I'm also rendering a collection using it. Here's what it looks like (notice the "#"):
##Show#View
<%= render 'my_partial/my_view', post: #post %>
##Collection ## (I'm not using the "#" symbol)
<%= render 'my_partial/my_view', post: post %>
#Mypartial
<% if #post.something? %>
## do this
<% else %>
## do that
<% end %>
And then I get the beautiful NoMethodError undefined methodsomething?' for nil:NilClass` page when using it in my collection. I know why I'm getting it, I'm just wondering what's the DRY way(s) of getting this to work? Should I just create another partial?
Thank you
Gave my solution below.. Though, it's probably not the best way...
Why are you referencing #post in your partial? You should use post instead, that is the entire point of what you are doing (passing variables to a partial as local variables).
You must change the rendering to:
<%= render 'my_partial/my_view', locals: { post: #post } %>
Take a look in the rails guide: http://guides.rubyonrails.org/layouts_and_rendering.html
Search for "3.4.4 Passing Local Variables" and you will find more information about this whole stuff.
And for fixing your collection problem also check out the rails guide and search for: "3.4.5 Rendering Collections".