NoMethodError in Rails: Passing variables - ruby-on-rails

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".

Related

Why can't find be used in the view as it is used in the controller?

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 %>

Is it possible to render a view with "get parameters"?

Is it possible to render a view with get parameters ?
For example, something like :
render "/projects/sheets?id=43"
It's because I need to render a view which uses url parameters to work properly.
I tried many ways, but it only creates parameters that I can get only in the controller and that are not available after.
It's because I want to have a view that contains the html code of many other views.
This is my current code :
allProjects.html.erb :
<% Project.where(productchief: user.id).order(:title).each do |project| %>
<%= render "/projects/sheets?id=#{project.id}" #This doesn't work. %>
<% end %>
It's because I want to have a view that contains the content of all the other views in my website to allow the users to print all this content in one time.
I don't think it's possible to do it in the way you are trying to do it. You will need to change /projects/sheets to be a partial and render that instead and pass through local variables.
So to clarify /projects/sheets.html.erb becomes /projects/_sheets.html.erb and you would then invoke as:
<%= render partial: "/projects/sheets", locals: { :project_id = project.id } %>
Then within the partial _sheets.html.erb you can make reference to project_id
Generally you should be able to access the params in a view but unless there's a very specific reason you can't, I suggested altering your routes. I may be missing some info from your original question, but let's say you have routes as:
get 'projects/sheets', to: "projects#index", as: :projects
get 'projects/sheets/:id', to: "projects#show", as: :project
That would change your urls a little but would still leave the params available. Using the routes above, for example and going to: localhost:3000/projects/sheets/5?something_fun=geeks_are_us will give the following params:
{"something_fun"=>"geeks_are_us", "controller"=>"projects", "action"=>"show", "id"=>"5"}
And if you're looking to render multiple items via a partial, you can pass the assigned variable for (in your case) 'project' to render the views but it is a partial as you appear to be rendering from a view already.
So something like:
<% #projects.each do |project| %>
<%= render partial: project, locals: {project: project} %>
<% end %>
This would try to render projects/_project.html.erb and sending project as a variable. If you need other variables in your view, just pass them in the locals hash.
Hope this is some help.

RoR undefined method 'to_datetime' depending on order of helper methods

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.

Specifying url in rails 3

i am totally new to rails programming... i used the request.path to get the current url and display it in all my views by specifying it in applications.html.erb. It is returning the entire path and i want to display it as a link... so i use
link_to to specify it as url..now here is what i want to do.. the url returned will be in the format path1/path2/path3..... i want to display it as path1>path2>path3 and as a link such that when the user clicks path1, it should take him to path 1 and so on...
this is the code i gave in html.erb file
but i get an error that says undefined method.... what should i do to accomplish that??
You could split the request.path on / and then build up the various links, but that could get really cluttered for deeply nested paths. I think a better approach would be to use something like breadcrumbs_on_rails and declare your breadcrumbs explicitly and render them in a partial or helper method. I think you could also use some Rails filter magic to have action names breadcrumbed automatically, but making the breadcrumbs explicit forces you to think about your site and your users more than programmatically vomiting out a string of links of unknown length.
You can do like this:
<% path = request.path %>
<% links = path.split('/') %>
<% ll="/" %>
<% links.each do |l| %>
<% ll += (l+'/') %>
<%= link_to l,ll %> >
<% end %>

Ruby On Rails - "undefined method `id' for 4:Fixnum"

I recently decided I wanted to list all the users in my Ruby On Rails application - since I couldn't figure out how to list them any other way, I decided to use partials.
I have the following on my administration page (just hooked up to a its own administration controller):
<%= render :partial => User.find(:all) %>
I then have a file called _user.html.erb in my users view folder. This contains the following:
<ul>
<% div_for #user.object_id do %>
<li><%= link_to user.username, user.username %></li>
<% end %>
</ul>
When the application runs and I go to the administration page, I get the following error:
undefined method `id' for 4:Fixnum
It says it's because of this line (which is in the partial file):
<% div_for #user.object_id do %>
I'm unsure why this happens (and have googled for hours to try and find results and only find solutions that don't work for me). I think it's something to do with my usage of the #user instance variable, but I'm not totally sure.
You get that error because div_for expects an active record object as an argument, which it calls the id method on. You pass in a fixnum (the result of #user.object_id), which is not an active record object and does not have an id method.
So pass in #user instead of #user.object_id and it will work.
Also you should use user instead of #user, rails 3 does not set instance variables for partials anymore.
Lose the .object_id part. I seriously can't think why are you using object_id!Do you have a good reason for doing so? Anyway div_for wraps a div around an object, so leave the .object_id part!
instead of object you are using it's column or visa varsa you are using at that time you will get this kind of error.
Example
I am using id instead of user = User.first object.
Try this, it worked for me.
#item.unit_of_measure.name
instead of
#item.unit_of_measure_id.name

Resources