Rails 3.1 associations? - ruby-on-rails

I have a Rails 3.1.1 application with the following models:
Company
Member
The two models have the following associations:
Company - has_many :members
Member - belongs_to :company
When adding members I can enter the company ID number and the record is linked successfully, I can lookup members through the company etc.
When I am working on the member show view I would like to 'pull' in details of the company.
Currently I have the following in the show view:
<h1>Listing members</h1>
<table>
<tr>
<th>Name</th>
<th>Mobile</th>
<th>Email</th>
<th>Qualifications</th>
<th>Membership</th>
<th>Company</th>
<th></th>
<th></th>
<th></th>
</tr>
<% #members.each do |member| %>
<tr>
<td><%= member.name %></td>
<td><%= member.mobile %></td>
<td><%= member.email %></td>
<td><%= member.qualifications %></td>
<td><%= member.membership %></td>
<td><%= #member.company.company_id %></td>
<td><%= link_to 'Show', member %></td>
<td><%= link_to 'Edit', edit_member_path(member) %></td>
<td><%= link_to 'Destroy', member, confirm: 'Are you sure?', method: :delete %></td>
</tr>
<% end %>
</table>
How do I go about pulling in a field from the related company? For example the company model has two fields (latitude and longitude).

Your loop should look like this:
<% #members.each do |member| %>
<tr>
<td><%= member.name %></td>
<td><%= member.mobile %></td>
<td><%= member.email %></td>
<td><%= member.qualifications %></td>
<td><%= member.membership %></td>
<td><%= member.company_id %></td>
<td><%= member.company.latitude %></td>
<td><%= link_to member.company.name, member.company %></td>
<td><%= link_to 'Show', member %></td>
<td><%= link_to 'Edit', edit_member_path(member) %></td>
<td><%= link_to 'Destroy', member, confirm: 'Are you sure?', method: :delete %></td>
</tr>
<% end %>
company_id is defined on the Member model, you cannot access it through member.company.company_id. To access a field on the related company model, use member.company.my_field.
These will only work in the members loop, as they access the |member| variable which is passed to the block.

#member.company.latitude
et cetera. Please let me know if you want clarification or more information.

Related

How to obtain count of comments

This is my Articles index.html.erb so far
<table>
<tr>
<th>Title</th>
<th>Text</th>
<th colspan="3"></th>
<th>Total Number of Comments Per Article</th>
</tr>
<% #articles.each do |article| %>
<tr>
<td><%= article.title %></td>
<td><%= article.text %></td>
<td><%= link_to 'Show', article_path(article) %></td>
<td><%= link_to 'Edit', edit_article_path(article) %></td>
<td><%= link_to 'Destroy', article_path(article),
method: :delete,
data: { confirm: 'Are you sure?' } %></td>
<td>Placeholder</td>
</tr>
<% end %>
</table>
<p>Total Number of Articles in database: <%= #count_of_articles %></p>
<h4>All Comments Written So Far</h>
<% #comments.each do |c| %>
<p><b><%= c.commenter %></b></p>
<p><%= c.body %></p>
<% end %>
<%= link_to 'New Article', new_article_path %>
This is my Article's index action
def index
#articles = Article.all
#count_of_articles = #articles.count
#comments = Comment.all
end
I am trying to figure out how to place the number of comments that each article has in the <td>Placeholder</td>
How do I do that?
EDIT
class Comment < ActiveRecord::Base
belongs_to :article
end
class Article < ActiveRecord::Base
has_many :comments, dependent: :destroy
validates :title, presence: true, length: { minimum: 5 }
end
by doing article.comments.count in the view you're basically running a sql query for each article in your db. Why not gather all records in your controller, and ask for the count in your view?, something like:
in the controller:
#comments_by_article = Comment.all.group_by(&:article_id)
and, in your view:
<td><%= #comments_by_article[article.id] && #comments_by_article[article.id].count || 0 %></td>
that way, rails will cache #comments_by_article in your controller, and you'll hitting the database once.
It is simply count:
<table>
<tr>
<th>Title</th>
<th>Text</th>
<th colspan="3"></th>
<th>Total Number of Comments Per Article</th>
</tr>
<% #articles.each do |article| %>
<tr>
<td><%= article.title %></td>
<td><%= article.text %></td>
<td><%= link_to 'Show', article_path(article) %></td>
<td><%= link_to 'Edit', edit_article_path(article) %></td>
<td><%= link_to 'Destroy', article_path(article),
method: :delete,
data: { confirm: 'Are you sure?' } %></td>
<td><%= article.comments.count %></td>
</tr>
<% end %>
</table>
article.comments is an ActiveRecord::Relation which extends the ActiveRecord::Calculations class containing the count method. The relation was defined in your model by you. Internally, ActiveRecord will call a COUNT SQL query to determine the number of comments that matches your article.
You can get the count with
article.comments.count

Image_tag First Image

Carrierwave use, I would like to show the first picture of a publication.
Try the following:
<% #autos.each do |auto| %>
<tr class="list">
<td><%= image_tag auto.fotos.first.to_s , size: "50x50" %></td>
<td><%= auto.ciudad %></td>
<td><%= auto.marca %></td>
<td><%= auto.modelo %></td>
<td><%= auto.version %></td>
<td><%= auto.año %></td>
<td><%= auto.hp %></td>
<td><%= auto.km %></td>
<td><%= link_to 'Show', auto %></td>
<td><%= link_to 'Edit', edit_auto_path(auto) %></td>
<td><%= link_to 'Destroy', auto, method: :delete, data: { confirm: 'Are?' }%></td>
</tr>
<% end %>
This makes it look like hexadecimal, not illustrated.
Any ideas?
You need to pass the image_tag an image URL. Instead of calling to_s on the model, you need to call url on the uploader attribute.
auto.fotos.first.foto.url

How do I connect a comment table to another table?

A pretty basic RoR question that I can't seem to find an answer to online:
I have two independent tables that were created with a scaffold.
lunches and comments. Relationships were not established during the scaffolding. I can redo the comments scaffold if needed.
I need to be able to take in and then display the related comments to every lunch in the lunch index view. Can someone tell me how to do that?
I edited the models\comment.rb to:
class Comment < ActiveRecord::Base
belongs_to :lunch
end
I edited the models\lunch.rb to:
class Lunch < ActiveRecord::Base
has_many :comments, dependent: :destroy
end
In the lunches view I have a loop that lists all the lunches columns:
<tbody>
<% #lunches.each do |lunch| %>
<tr class="<%= cycle('list_line_odd', 'list_line_even')%>">
<td><%= lunch.company %></td>
<td><%= lunch.person %></td>
<td><%= lunch.email_submit_lunch %></td>
<td><%= lunch.company_contact %></td>
<td class="list_description"><%= truncate(strip_tags(lunch.description), length: 40) %></td>
<td><%= lunch.date %></td>
<td><%= lunch.price %></td>
<td class="list_actions"><%= link_to 'Show', lunch %></td>
<td class="list_actions"><%= link_to 'Edit', edit_lunch_path(lunch), data: { confirm: 'Are you sure?' } %></td>
<td class="list_actions"><%= link_to 'Destroy', lunch, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
** Edit: I have redone the comments table to contain the lunch_id foreign key. How would I pass this foreign key (lunch_id) from the lunch view into the comment creation process?
You should use comments relation on lunch model.
If you established it correctly, then you can try something like:
<tbody>
<% #lunches.each do |lunch| %>
<tr class="<%= cycle('list_line_odd', 'list_line_even')%>">
<td><%= lunch.company %></td>
<td><%= lunch.person %></td>
<td><%= lunch.email_submit_lunch %></td>
<td><%= lunch.company_contact %></td>
<td class="list_description"><%= truncate(strip_tags(lunch.description), length: 40) %></td>
<td><%= lunch.date %></td>
<td><%= lunch.price %></td>
<td>
<%- lunch.comments.each do |comment| %>
<p><%= comment.body %></p>
<% end %>
</td>
<td class="list_actions"><%= link_to 'Show', lunch %></td>
<td class="list_actions"><%= link_to 'Edit', edit_lunch_path(lunch), data: { confirm: 'Are you sure?' } %></td>
<td class="list_actions"><%= link_to 'Destroy', lunch, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
UPD:
class CommentsController < ApplicationController
def create
lunch = Lunch.find(params[:lunch_id])
lunch.comments.create!(comment_params)
end
private
def comment_params
params[:comment].permit(:body)
end
end
In such case, when you post form to create comment, you should add lunch_id to form params, like:
lunch_path(lunch_id: lunch.id)
This is the main idea. But implementation can depend of your business logic. For example where do you locate new comment form and other conditions.
You didn't mention it in the description, but you will need to add the column lunch_id to the comments table (if you haven't already) for the relationship to work.
By defining that Lunch has_many :comments Rails will create a instance method for Lunch called comments that will return the associated comments.
In your view you can do something like this to display the comments.
<tbody>
<% #lunches.each do |lunch| %>
<tr class="<%= cycle('list_line_odd', 'list_line_even')%>">
<td><%= lunch.company %></td>
<td><%= lunch.person %></td>
<td><%= lunch.email_submit_lunch %></td>
<td><%= lunch.company_contact %></td>
<td class="list_description"><%= truncate(strip_tags(lunch.description), length: 40) %></td>
<td><%= lunch.date %></td>
<td><%= lunch.price %></td>
<ul>
<% lunch.comments.each do |comment| %>
<li><%= comment %></li>
<% end %>
</ul>
<td class="list_actions"><%= link_to 'Show', lunch %></td>
<td class="list_actions"><%= link_to 'Edit', edit_lunch_path(lunch), data: { confirm: 'Are you sure?' } %></td>
<td class="list_actions"><%= link_to 'Destroy', lunch, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
You will definitely need to establish a FK for lunches in the comments table. Adjust your migration to include:
create_table "comments" do |t|
t.string :body
t.integer :lunch_id
end
Then to display the comments, just loop through the comments on each lunch in your index view:
<td>
<% lunch.comments.each do |comment| %>
<p><%= comment.body %></p>
<% end %>
</td>
From what I understand you created both model scaffolds independently. This means that your db tables are not connected.
To actually make an association you have to add a column to comments table "lunch_id" (which would tell Rails to which lunch does the comment belong).
You can do this by running
rails g migration AddLunchIdToComment
after that open the newly created migration file and add the line
add_column, :comments, :lunch_id, :integer
inside the change function.
after that do rake db:migrate
Now you can access lunch related comments with lunch.comments method inside your view loop. This should make your code work (don't forget to restart the server).

Rails nested Resources Error

I have this nested recourses
resources :products do
resources :senders
end
In my products/index view I have this
...
..
.
<td><%= link_to 'Show Email Addresses', product_senders_path(product) %> </td>
.
..
...
which seemed to be working and it redirected me to the senders of that product. Now for some strange reason I get this:
NameError in Senders#index
undefined local variable or method `sender_path' for #<#<Class:0x00000003cb1f58>:0x00000003b46e48>
Extracted source (around line #18):
15: <td><%= sender.product_id %></td>
16: <td><%= sender.name %></td>
17: <td><%= sender.email %></td>
18: <td><%= link_to 'Show', sender %></td>
19: <td><%= link_to 'Edit', edit_sender_path(sender) %></td>
20: <td><%= link_to 'Destroy', sender, confirm: 'Are you sure?', method: :delete %></td>
21: </tr>
This is my sender/index file:
<h1>Listing senders</h1>
<table>
<tr>
<th>Application</th>
<th>Name</th>
<th>Email</th>
<th></th>
<th></th>
<th></th>
</tr>
<% #senders.each do |sender| %>
<tr>
<td><%= sender.product_id %></td>
<td><%= sender.name %></td>
<td><%= sender.email %></td>
<td><%= link_to 'Show', sender %></td>
<td><%= link_to 'Edit', edit_sender_path(sender) %></td>
<td><%= link_to 'Destroy', sender, confirm: 'Are you sure?', method: :delete %></td>
</tr>
<% end %>
</table>
<br />
Why I am getting this error? Before it was working fine
As there are only nested routes for senders, there are no edit_sender_path(sender) helper, only edit_product_sender_path(product, sender)
You may see a list of all application route helpers by executing rake routes

Block List Question

I have the following code in one of my views:
<% #videos.each do |i| %>
<tr class="<%= cycle("even","odd") %>">
<td><%= i.title %></td>
<td><%= i.premiere %></td>
<td><%= i.film_type %></td>
<td><%= i.preferred_date %></td>
<td><%= i.actual_date %></td>
<td><%= i.created_at %></td>
<td><%= i.updated_at %></td>
<td><%= i.size %></td>
</tr>
<% end %>
It is listing all of the items in a table (which is then sortable) from each video. I want to make the title link to the video that the title belongs to. Could someone please show me how to make i.title into a link? I tried lots of formats and none of them seem to work.
Thank you!
To link to Rails' standard "show" action for the video:
<td><%= link_to(i.title, video_path(i)) %></td>
This assumes that i.class == Video and you have map.resources :videos in your routes.

Resources