How do I connect a comment table to another table? - ruby-on-rails

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

Related

Getting the name of a field referenced by an id

Hello Stackoverflow heroes,
I have an users table with the following field:
authorization_id
And i have an authorizations table with just a regular id.
I tried renaming id to authorization_id but it just added another column called authorization_id it didn't change the id column.
What i am trying to achieve to be able to do
<% #user.each do |user| %>
<tr>
<td><%= user.name %></td>
<td><%= user.authorization_id.name %></td>
<td><%= user.email %></td>
<td><%= link_to 'Show', user %></td>
<% if admin? %>
<td><%= link_to 'Edit', edit_user_path(user) %></td>
<td><%= link_to 'Destroy', user, :confirm => 'Are you sure?',
:method => :delete %></td>
<% end %>
</tr>
<% end %>
But it won't work i suspect that authorization_id is has not been linked to the autorizations table. But i can't seem to find out how to do it.
This is my authorization model
class Authorization < ActiveRecord::Base
belongs_to :user
validates :name, presence: true, length: {minimum: 3}
end
and this is a piece of my user model
class User < ActiveRecord::Base
has_one :authorization
Any help will be welcomed,
Kind regards.
It seems this:
<td><%= user.authorization_id.name %></td>
Should simply be this:
<td><%= user.authorization.name %></td>
You don't need _id.
Also, I think your associations are backwards (the belongs_to model should hold the foreign key). Check the Guide.
First of all, Authorization belongs to User, so the foreign key must be in Authorization model, eg we name it user_id.
So what we need to modify is add the foreign key user_id to Authorization model, that is enough.
Then your view is much easier:
<% #user.each do |user| %>
<tr>
<td><%= user.name %></td>
<td><%= user.authorization.name %></td> <!-- Change here! -->
<td><%= user.email %></td>
<td><%= link_to 'Show', user %></td>
<% if admin? %>
<td><%= link_to 'Edit', edit_user_path(user) %></td>
<td><%= link_to 'Destroy', user, :confirm => 'Are you sure?',
:method => :delete %></td>
<% end %>
</tr>
<% end %>

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

How to displaying an specific attributes with a many to many association in rails

I have a two way many-to-many assoication between 3 models: work.rb, category.rb, categorywork.rb
Within the work#index using <%= work.categories %> renders some wonky looking html markup
<% #works.each do |work| %>
<tr>
<td><%= work.name %></td>
<td><%= work.subtitle %></td>
<td><%= work.categories %></td>
<td><%= link_to 'Show', work %></td>
<td><%= link_to 'Edit', edit_work_path(work) %></td>
<td><%= link_to 'Destroy', work, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
I'm trying to target speific attributes of the association like "name".
Unfortunately when using <%= work.categories.name %> it gets weirder with:
How do i target just the name or just the description?
Try this out:
<%= work.categories.pluck(:name) %>

How to make table row to work as hyperlink in Ruby on Rails?

how to make the rows of my user index view which i generated using scaffolding, to work as a hyperlink to the show user action. after clicking anywhere on the user row it will show us the corresponding user. it is also acceptable if i can make link to a division.
code
<table>
<tr>
<th>Username</th>
<th></th>
<th>email</th>
<th>roll_no</th>
</tr>
<% #users.each do |user| %>
<tr >//i want to make these rows as link
<% if user.username!='admin' %>
<td><%= user.username %></td>
<td><%= user.email %></td>
<td><%= user.roll_no %></td>
<td><%= link_to 'show', #user %></td><br/>
<td><%= link_to 'Delete', user, confirm: 'Are you sure?', method: :delete %></td>
<% end %>
</tr>
As meager said, you should use JavaScript. Something like this:
$('tr').click(function(){
document.location.href='the_link_to_go_to';
})
You can modify it to suit your needs.

Rails 3.1 associations?

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.

Resources