Rails resources routes miss parameters yet match documentation - ruby-on-rails

Using Rails' resources directive, I have created a set of routes for a controller (contacts). I'm now editing the default views they come with to include some of my own content. However, the link_to method is failing, telling me that I'm missing a required parameter.
No route matches {:action => 'show', :controller => 'contacts', :id => nil} missing required keys [:id]
It's obvious why this is happening - the link_to method is not being supplied with an ID, instead it's getting nil. However, the code I'm using matches the documentation for link_to.
This is the view in question:
<% #contacts.each do |contact| %>
<tr>
<td><%= contact.first %></td>
<td><%= contact.last %></td>
<td><%= contact.title %></td>
<td><%= contact.city %></td>
<td><%= contact.phone %></td>
<td><%= contact.email %></td>
<td><%= link_to 'Show', contact %></td>
<td><%= link_to 'Edit', edit_contact_path(contact) %></td>
<td><%= link_to 'Delete', contact.id, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
#contacts is a set of contacts returned from the controller. The line that sets that is:
#contacts = Contact.select("title, first, last, city, phone, email")
.where("created_by" => #current_user.id)
The relevant content of the routes.rb file is simply resources :contacts.
The documentation states:
Because it relies on url_for, link_to supports both older-style controller/action/id arguments and newer RESTful routes. Current Rails style favors RESTful routes whenever possible, so base your application on resources and use [...]
link_to "Profile", #profile
This appears to be what I'm using with link_to 'Show', contact.
Why is the ID not getting passed to link_to?
What can I do to remedy this?

Change
Contact.select("title, first, last, city, phone, email")
to
Contact.select("title, first, last, city, phone, email, id")
the contact's id is nil because it isn't in the select query.
Also, although it doesn't seem to be causing problems right now, I would reccomend using an array of symbols instead of a comma-separated string, so that the sql query is more specific. For example:
Contact.select("title, first").to_sql #=> SELECT title, first FROM contacts
Contact.select(:title,:first).to_sql #=> SELECT "contacts"."title", "contacts"."first" FROM contacts
This way if you do a join with another model, it won't complain about the unspecific id in select. If you feel like you're typing too much, you can use the %i(...) syntax:
Contact.select(*%i(title first last city phone email))

Your code seems fine.
Maybe you have an instance in the #contacts array that is not saved and therefore, has no id?
Another way to put the same (again, your code is fine) would be:
= link_to 'Show', contact_path(contact)
I would suggest posting the routes file.

Related

Ruby show associated asset data in table

I'm new to RoR, so please be gentile. I'm not sure, if I search for the right topic. However, I've spent the whole day trying to figure out, how to work with the has_man, belongs_to and so forth asset associations.
Right now I have two assets:
sqlite> pragma table_info(meetups);
0|id|INTEGER|1||1
1|name|varchar(255)|0||0
2|owner|integer|0||0
3|dateOfInception|datetime|0||0
4|homeTown|varchar(255)|0||0
5|created_at|datetime|0||0
6|updated_at|datetime|0||0
7|activity_id|integer|0||0
sqlite> pragma table_info(activities);
0|id|INTEGER|1||1
1|name|varchar(255)|0||0
2|location|varchar(255)|0||0
3|startDate|datetime|0||0
4|duration|integer|0||0
5|description|varchar(255)|0||0
6|created_at|datetime|0||0
7|updated_at|datetime|0||0
8|image|varchar(255)|0||0
9|meetup_id|integer|0||0
So I can create a new meetup and select multiple saved activities. For every meetup we can select a multiple activities. If I create a meetup, they corresponding activities are also stored correctly, as you can see in the image below:
Image
However, it's not useful to output them just like an array. It would be great, if the activity name would appear. But how is that possible? I tried so many things, renaming the db foreign keys, create a find method in the meetup controller... but nothing worked. Please help me out here - I think I'm very near but someting I dont know doesnt work.
<% #meetups.each do |meetup| %>
<tr>
<td><%= meetup.name %></td>
<td><%= meetup.owner %></td>
<td><%= meetup.dateOfInception %></td>
<td><%= meetup.homeTown %></td>
<td><%= meetup.activity_ids %></td>
<td><%= link_to 'Show', meetup %></td>
<td><%= link_to 'Edit', edit_meetup_path(meetup) %></td>
<td><%= link_to 'Destroy', meetup, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
class MeetupsController < ApplicationController
before_action :set_meetup, only: [:show, :edit, :update, :destroy]
# GET /meetups
# GET /meetups.json
def index
#meetups = Meetup.all
end
Many thanks for your help!
Try this in your view:
meetup.activities.map(&:name).join(',')
That should show the data you want. For performance reasons, you'll want to add .include(:activities) to
the controller action that loads your list of meetups.
It sounds like you're trying to model a Has And Belongs To Many relationship, though? You'll need a third table to model that correctly.
If that's not what you're wanting to model, you should remove the activity_id column from the meetups table.

undefined method `name' for nil:NilClass

I have this problem on te line
<td><%= h box.manufacturer.name %></td>
of
<% #boxes.each do |box| %>
<tr>
<td><%= h box.manufacturer.name %></td>
<td><%= h box.model %></td>
<td><%= link_to 'Mostrar', :action => 'show', :id => box %></td>
<td><%= link_to 'Editar', :action => 'edit', :id => box %></td>
<td><%= button_to 'Eliminar', { :action => 'destroy', :id => box },
:confirm => "Are you sure you want to delete box #{box.model}?" %></td>
manufacturers is a table with field called name,its supposed that an object manufacturer has member called name ,isn it?
It's quite clear one of your box records doesn't have its associated manufacturer. If it's acceptable, you can use Object#try method, like this:
<%= box.manufacturer.try(:name) %>
If it's not, you should think of adding proper validation to Box model:
validates_presence_of :manufacturer
I didn't use h helper because in Rails >= 3.0 (which you probably use) untrusted content is escaped automatically.
It means your one of your boxes doesn't have a manufacturer.
You can prevent an exception like this by using try:
box.try(:manufacturer).try(:name)
If the manufacturer doesn't exist, it will return nil instead of throwing an exception
Yes, but in your case you seem to have a box with no manufacturer.
<%= h box.manufacturer.name if box.manufacturer %>
Or
<%= h box.manufacturer.try(:name) %>
The proposed solutions fix the issue but don't address the bug in architecture. I recommend learning the Tell Don't Ask principle.
Your views shouldn't do any checks on nil as it is not their responsibility. You should always try to avoid long method chains as it will always fail on certain step.
Refactor your application like this:
box.rb:
def manufacturer_name
manufacturer.try(:name)
end
view:
<td><%= h box.manufacturer_name %></td>
I don't think it's possible if the box is nil. If it is - then I recommend removing nils from the array before iterating over it in views like this:
controller:
#boxes = box_retrieving_method_with_nils.compact

How to display paperclip's uploads.

Im currently building a blog. While the paperclip photos pop up inside the individual blog posts they don't seem to pop up in the index, where all the blog posts are displayed.
13th line seems to be the problem.
this is my index.html.erb for my posts
10 <% #posts.each do |post| %>
11 <tr>
12 <td><%= link_to post.title, post_path(post) %></td>
13 <td><%= image_tag #post.picture(:medium) %></td>
14 <td><%= post.text %></td>
15 <td><%= link_to 'Show', action: :show, id: post.id %></td>
16 <td><%= link_to 'Edit', action: :edit, id: post.id %></td>
17 <td><%= link_to 'Destroy', { action: :destroy, id: post.id },
18 method: :delete, data: { confirm: 'Are you sure?' } %></td>
it throws me a no method error.
Please let me know if I can give you extra files if you need more information
Thank you in advance!
You're not passing the URL for the image to the image_tag helper.
You need to display your image like this:
<%= image_tag post.picture.url(:medium) %>
You're trying to access the #post instance variable, but that instance variable doesn't exist. Rather, within your loop, you should access your post local variable as such:
<%= image_tag post.picture.url(:medium) %>
Note also that, from the documentation, the correct syntax to access variations of a Picture instance involves passing the variation name to the url attribute:
post.picture(:medium) # Invalid
post.picture.url(:medium) # Valid!
As mentioned by Jon, you need to use the .url method on your picture object (official documentation):
<%= image_tag post.picture.url(:medium) %>
Paperclip
The reason for this is Paperclip actually creates its own picture object & attaches several methods to that (url being one of them). This means you have to call url each time you show the post's image to get it to load
Normally, you'd be able to call methods on your instance or local variables, but as Paperclip actually creates its own object, you have to use its in-built methods to get it to work correctly

email Model and email column clashing in Rails

I have a Submitter Model which has an email column. I also have an Email Model that has email suffix column in it.
My issue (I believe) is that since my Submitter Model has an email column, when I try to use submitter.email.suffix to display the suffix in my Email model it says there's no defined method.
Any idea what I can do here?
View:
<% #submitters.each do |submitter| %> <tr>
<td><%= submitter.school.name %></td>
<td><%= submitter.first_name %></td>
<td><%= submitter.last_name %></td>
<td><%= submitter.email %><%= submitter.email.suffix %></td>
<td><%= link_to 'Show', submitter %></td>
<td><%= link_to 'Edit', edit_submitter_path(submitter) %></td>
<td><%= link_to 'Destroy', submitter, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</table>
As a side note I have no problem showing the IDs of the emails suffix but obviously I'm trying to show the actual suffix instead:
<td><%= submitter.email %><%= submitter.email_suffix_id %></td>
Submitter.rb has a has many :emails and Email.rb has a belongs_to :submitter association.
So let's break this down. You say you're trying to do
submitter.email.suffix
however, your model has no such :email association. Instead you've stated your Submitter model has
has_many :emails
This would mean:
To print the :email attribute on some Submitter instance submitter, use
puts submitter.email
To print the :prefix attribute of each Email instance related to submitter via your has_many association, you'd need to loop over them
submitter.emails.each do |e|
puts e.suffix
done
It's still quite unclear what exactly you're trying to do, but hopefully this clears up some confusion on your end; there is no method naming conflict so far.
submitter.email.suffix won't work because it returns Submitter "email" which is a string, not the Email instance.
submitter.emails.each(&:suffix)
should work. submitter.emails will return an Email's instances and they do have suffix method(according to your words).

Rails 3 - Nested Routes "NoMethodError" despite being listed in rake routes

Ok guys so I have a nested route like this:
resources :apps do
resources :forms
end
In my form index I have this block:
<% #forms.each do |form| %>
<tr>
<td><%= form.app_id %></td>
<td><%= form.title %></td>
<td><%= link_to 'Show', app_form(#app,form) %></td>
<td><%= link_to 'Destroy', form, :confirm => 'Are you sure?', :method => :delete %></td>
</tr>
<% end %>
</table>
The page throws a NoMethodError on the app_form line; however I think I am passing in the app and form in correctly (I've also tried to pass in the #app.id). Calling rake routes... the route is even displayed:
app_form GET /apps/:app_id/forms/:id(.:format) {:controller=>"forms", :action=>"show"}
Any help would be greatly appreciated!
Try app_form_path(#app, form) instead (you need to append _path to the route name).
Not only nested routes,For each routes you using, You need to append _path or _url with route name.
So here juz try app_form_path(#app,form) or app_form_url(#app,form)

Resources