Get attribute from join model (belongs_to) rails - ruby-on-rails

I have 2 related models.
class Store < ActiveRecord::Base
attr_accessible :name, :subdomain
belongs_to :theme
end
class Theme < ActiveRecord::Base
attr_accessible :name, :description, :screenshot_attributes
has_many :stores
end
Everything works fine the problem is when I try to access the theme's name in the following way.
<% #stores.each do |store| %>
<tr>
<td><%= link_to store.subdomain, store %></td>
<td><%= store.name %></td>
<td><%= store.theme.name %></td>
<td><%= link_to 'Go to Store', root_url(subdomain: store.subdomain) %></td>
<td><%= link_to 'Edit', [:edit, store] %></td>
<td><%= link_to 'Destroy', store, confirm: 'Are you sure?', method: :delete %></td>
</tr>
<% end %>
This is the line that gets the error.
<td><%= store.theme.name %></td>
And this is the message:
undefined method `name' for nil:NilClass
What is the correct way to access the theme's name value?
Thankyou!

Just because store.theme is nil. A usefull function is inspect. If you do:
<%= store.inspect %>
You will see theme_id is nil.

Related

Deleting a post after deleting a user associated with the post in rails

I have implemented an admin model in rails that would allow me to have a list of users, and as the admin, I am able to delete the users. Some users wrote posts-- my issue is when I (the admin) delete a user that wrote a post and then destroy the post, I get an error that states: "undefined method `name' for nil:NilClass
nil:NilClass."
<% #reviews.each do |review| %>
<tr>
<td><%= review.user.name%></td>
<td><%= review.location %></td>
<td><%= review.program %></td>
<td><%= review.semester %></td>
<td><%= review.review %></td>
<td><%= link_to 'Show', review %></td>
<td><%= link_to 'Edit', edit_review_path(review) %></td>
<td><%= link_to 'Destroy', review, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
Associate the post with user with dependent destroy.
i.e.
User Model
class User < ActiveRecord::Base
has_many :posts, dependent: :destroy
end
Post Model
class Post < ActiveRecord::Base
belongs_to :user
end
The posts will be deleted automatically.

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 access first_name and last_name from belongs_to assocation rails

I'm trying to access the first_name and last_name, two columns of an associated table, of a user by referencing the user_id column in a different table, but I don't know how to. Any tips?
Here's the view in which I try to reference it
<% #allhours.each do |hour| %>
<tr id="dashfield">
<td><%= hour.user_id %></td>
<td><%= hour.assignment %></td>
<td><%= hour.hours %></td>
<td><%= hour.supervisor %></td>
<td><%= hour.date %></td>
<td><%=form_for(:hour_log, method: :put) do |f|%>
<%= f.hidden_field :status, :value => 'Confirmed' %>
<%= f.submit 'Validate'%>
<%end%></td>
</tr>
<% end %>
I'd like to replace the "user_id", which is a number, to first_name and last_name. Thanks!
You have to have like :
<td><%= hour.user.first_name %></td>
<td><%= hour.user.last_name %></td>
Inside the controller do below to avoid N + 1 query issues:
#allhours = AllHours.includes(:user)
# change the code as per your need, but idea is to include the `user`
# association in advance.

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

Newbie stuck with fields_for and nested attributes in rails

Rails newbie here. I'm stuck on fields_for in Rails, and would be eternally grateful for anyone's help.
In Events#new, why am I getting NoMethodError?
Error message says undefined method `name'
In Events, why am I getting NameError?
Error message says undefined local variable or method 'event'.
I am trying to create and view a form where each event has 2 fields for each friend.
_form.html.erb:
<%= form_for(#event) do |f| %>
<div class="field">
Date: <%= f.text_field :date %></br>
Friends: <%= f.fields_for :friends do |friends_fields| %>
<%= friends_fields.text_field :name %>
<% end %>
<% end %>
index.html.erb:
<tbody>
<% #events.each do |event_form| %>
<tr>
<td><%= event_form.date %></td>
<td><%= event_form.friends.each do |friend| %>
<%= friend.name %>
<% end %>
</td>
<td><%= link_to 'Show', event %></td>
<td><%= link_to 'Edit', edit_event_path(event) %></td>
<td><%= link_to 'Destroy', event, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
event.rb:
class Event < ActiveRecord::Base
has_many :friends
accepts_nested_attributes_for :friends, allow_destroy: true
end
friend.rb:
class Friend < ActiveRecord::Base
belongs_to :event
end
events_controller.rb:
def new
#event = Event.new
2.times { #event.friends.build }
end
Event is not defined because events iterator uses event_form instead of event variable name in each iteration. Try changing to this:
<tbody>
<% #events.each do |event| %>
<tr>
<td><%= event.date %></td>
<td><%= event.friends.each do |friend| %>
<%= friend.name %>
<% end %>
</td>
<td><%= link_to 'Show', event %></td>
<td><%= link_to 'Edit', edit_event_path(event) %></td>
<td><%= link_to 'Destroy', event, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>

Resources