Rails show string not ID in index - ruby-on-rails

I have the following form where a user selects a department from a list of database entries on the activity centers page. I am trying to display the department string (:department) instead of the department ID. I tried #activity_center.department.department but that isn't working. Any suggestions?
Form:
<%= f.select :department_id, options_from_collection_for_select(#departments, 'id', 'department'), hide_label: true, :multiple => false %>
Departments Model:
class Department < ActiveRecord::Base
validates :department, :presence => true
has_many :activity_centers
end
Activity Centers Model:
class ActivityCenter < ActiveRecord::Base
validates :activity_center, :presence => true
validates :department_id, :presence => true
belongs_to :departments
end
Activity centers index page:
<% #activity_centers.each do |activity_center| %>
<tr>
<td><%= activity_center.activity_center %></td>
<td><%= activity_center.department.department %></td>
<td style="text-align:right;">
<%= link_to 'View Activity Center', activity_center_path(activity_center), class: "btn btn-success btn-xs" %>
<%= link_to 'Edit', edit_activity_center_path(activity_center), class: "btn btn-default btn-xs" %>
<%= link_to 'Delete', activity_center_path(activity_center), class: "btn btn-danger btn-xs",
method: :delete,
data: { confirm: 'Confirm you want to delete this activity_center.' } %></td>
</tr>
<% end %>

Per MZaragoza it was a typo. belongs_to is supposed to be singular.

Related

Display name of user all users who have liked a particular post

I want to name(s) of all user who have liked a post.
I have 4 models: user,post,like and review.
A user can have many posts.
Post can reviews && post can have many likes.
I am able to count likes on post but i am not able to display name of users who have liked a post.
Like Model:
class Like < ApplicationRecord
belongs_to :post
belongs_to :user
end
Post Model
class Post < ApplicationRecord
belongs_to :user
has_many :reviews, dependent: :destroy
has_many :likes, dependent: :destroy
validates :title, presence: true
validates :body, presence: true
end
Review Model:
class Review < ApplicationRecord
belongs_to :user
belongs_to :post
end
User Model:
class User < ApplicationRecord
before_create { generate_token(:auth_token) }
before_save { self.email = email.downcase }
has_secure_password
has_many :posts
has_many :reviews
has_many :likes
validates :name, presence: true
validates :email, presence: true, uniqueness: true
validates :password, confirmation: true
validates :password_confirmation, presence: true, unless: Proc.new { |a| !a.new_record? && a.password.blank? }
def send_password_reset
generate_token(:reset_password_token)
self.reset_password_sent_at = Time.zone.now
save!
UserMailer.password_reset(self).deliver
end
def generate_token(column)
begin
self[column] = SecureRandom.urlsafe_base64
end while User.exists?(column => self[column])
end
end[![enter image description here][1]][1]
_post.html.erb
<h1> Posts ( <%= #posts.count %> ) </h1>
<% #posts.each do |p| %>
<div class="form-field">
<h4>
<b><%= p.title %></b>
<%= link_to "Edit", edit_post_path(p.id), class: "btn btn-warning col-md-2-offset", style: "align-right" %>
<%= link_to "Delete", p, method: :delete, class: "btn btn-danger col-md-2-offset" ,data: { confirm: "You sure? "}, style: "align-right" %>
<% if p.reviews.count > 0 %>
<%= link_to "View Comments", review_path(p.id), class: "btn btn-primary" %>
<% end %>
</h4>
<%= p.body %>
<br>
<% if p.likes.count > 0 %>
Likes: <%= p.likes.count %>
<% end %>
<br>
<% if Like.find_by(user_id: current_user.id,post_id: p.id) %>
<%= link_to " UnLike ", like_path(p.id), method: :delete,class: "btn btn-
primary fa fa-thumbs-down" %>
<% else %>
<%= link_to " Like ", post_likes_path(p.id), method: :post, class: "btn btn-
primary fa fa-thumbs-up" %>
<% end %>
<br>
</div>
<% end %>
I was trying something like this,
I need to connect user,like and post table, for post which has been liked by some user.
I somehow need to merge two-three queries.
#like is an array,
instead use
#like = #liked.where(post_id: 7).first
Then try #like.user
First I hope you use eager loading to prevent the N+1 issue, when loading likes of a post, and their users
Second
I would suggest changing this peace of code
<% if Like.find_by(user_id: current_user.id,post_id: p.id) %>
<%= link_to " UnLike ", like_path(p.id), method: :delete,class: "btn btn-primary fa fa-thumbs-down" %>
<% else %>
<%= link_to " Like ", post_likes_path(p.id), method: :post, class: "btn btn-primary fa fa-thumbs-up" %>
<% end %>
With
<% if p.likes.find_by(user_id: current_user.id) %>
<%= link_to " UnLike ", like_path(p.id), method: :delete, class: "btn btn-primary fa fa-thumbs-down" %>
<% else %>
<%= link_to " Like ", post_likes_path(p.id), method: :post, class: "btn btn-primary fa fa-thumbs-up" %>
<% end %>
This will not perform additional DB request
And finnally how to shows user name of each user that has liked the post
I would suggest creating a helper method for this, as it may be need for multiple places
def liked_by_users(post)
post.likes.map do |like|
like.user.username
end.join(', ')
end
Are you just trying to get the names of users that have liked a post to display them? If that's the case you can add a function to one of your controllers called something like get_likes_for(post_id) that will return an array of all the users that liked a post:
def get_likes_for(pid)
users = []
Like.where(post_id: pid).each do |l|
users << User.find_by(id: l.user_id).name
end
users
end
Then you can list them in your post controller like this:
<% if p.likes.count > 0 %>
Likes: <%= p.likes.count %>
Liked By: <%= get_likes_for(p.id).to_s %>
<% end %>
This won't exactly connect the three models like the last part of your posts asks, but it will at least allow you to display the users who have liked a post.

rails multi-level nested forms with cocoon and tables

I've successfully implemented one level of nested form with Cocoon and tables. However, I'm having a difficult time wrapping my mind on how to do another nested level. My issue is how to do this with a table. And maybe a table isn't the write way to go at all. Thank you for helping a newbie.
Here are my models:
class Profession < ApplicationRecord
has_many :procedure_categories, dependent: :destroy
accepts_nested_attributes_for :procedure_categories, allow_destroy: true
end
And:
class ProcedureCategory < ApplicationRecord
belongs_to :profession
has_many :procedures
accepts_nested_attributes_for :procedures, allow_destroy: true
end
And:
class Procedure < ApplicationRecord
belongs_to :procedure_category
end
Here is my top level form code:
<%= form_for(#profession) do |f| %>
<%= render 'shared/profession_error_messages' %>
<%= f.label :profession %>
<%= f.text_field :profession, class: 'form-control' %>
<%= f.label :description %>
<%= f.text_field :description, class: 'form-control' %>
<%= f.label :active, class: "checkbox inline" do %>
<%= f.check_box :active %>
<span>Active profession?</span>
<% end %>
<table class='table'>
<thead>
<tr>
<th>Category</th>
<th>Description</th>
<th>Display Order</th>
<th>Selection Type</th>
<th>Delete</th>
<th>Edit</th>
</tr>
</thead>
<tbody class="categories">
<%= f.fields_for :procedure_categories do |procedure_category| %>
<%= render 'procedure_category_fields', f: procedure_category %>
<% end %>
</tbody>
</table>
<%= link_to_add_association 'Add Category', f, :procedure_categories,
data: { association_insertion_node: '.categories', association_insertion_method: :append } %>
<br><br>
<%= f.submit "Save", class: "btn btn-primary" %>
<% end %>
And the next partial one level down:
<tr class="nested-fields">
<td><%= f.text_field :category, class: 'form-control' %></td>
<td><%= f.text_field :description, class: 'form-control' %></td>
<td><%= f.text_field :display_order, class: 'form-control' %></td>
<% cs = options_for_select(controls, f.object.selection_type) %>
<td><%= f.select :selection_type, cs, class: 'form-control' %></td>
<td><%= link_to_remove_association "Remove Category", f %></td>
<% if f.object != nil %>
<td><%= link_to "Category", edit_procedure_category_path(#profession,f.object) %><td></td>
<% end %>
</tr>
So, I'm struggling with how to implement the final level of nesting (procedures).
Thank you for listening.
Use has_many :through
Here are my models:
class Profession < ApplicationRecord
has_many :procedures, through: categories
has_many :categories, dependent: :destroy
accepts_nested_attributes_for :categories, allow_destroy: true
end
Rename this procedure_category model in category
class Category < ApplicationRecord
belongs_to :profession
has_many :procedures
accepts_nested_attributes_for :procedures, allow_destroy: true
end
And:
class Procedure < ApplicationRecord
belongs_to :category
end
If I miss something you can check the instruction from the rails guide
The controller professions#new action should create the following variables, so that they are available in the view:
def new
#profession = Profession.new
#categories = #profession.categories.build
#procedures = #categories.procedures.build
end
The view uses that variable so store the user inputs and make a post request at /profession/ with those inputs stored in the parameters hash
<%= form_for(#profession) do |f| %>
<%= f.fields_for :categories do |category| %>
<%= category.fields_for :procedures do |precedure| %>
<% end %>
<% end %>
<% end %>
The fields_for yields a form builder. The parameters' name will be what accepts_nested_attributes_for expects. For example, when creating a user with 2 addresses, the submitted parameters would look like:
This is how your parameters should look like:
{
'profession' => {
'name' => 'John Doe',
'categories_attributes' => {
'0' => {
'kind' => 'Home',
'street' => '221b Baker Street',
'procedures_attributes' => {
'0' => {},
'1' => {}
}
},
'1' => {
'kind' => 'Office',
'street' => '31 Spooner Street'
}
}
}
}
so make sure your form is pointing at post url /professions/ and that the routing will trigger the professions#create action
def create
binding.pry
end
for any problems set a binding pry and check in your console how your parameters are showing up.
Read more at
http://guides.rubyonrails.org/form_helpers.html#building-complex-forms

link_to_add_association creating extra forms in a multi-level nested environment

My issue is best described with a picture:
extra forms added issue
Here is the top model:
class Profession < ApplicationRecord
has_many :procedure_categories, dependent: :destroy
accepts_nested_attributes_for :procedure_categories, allow_destroy: true
end
And second:
class ProcedureCategory < ApplicationRecord
belongs_to :profession
has_many :procedures
accepts_nested_attributes_for :procedures, allow_destroy: true
end
And third:
class Procedure < ApplicationRecord
belongs_to :procedure_category
end
Here is where the code is that is causing the issue including the link_to_add_association method.
<div class="nested-fields">
<%= f.label :category %>
<%= f.text_field :category, class: 'form-control' %>
<%= f.label :description %>
<%= f.text_field :description, class: 'form-control' %>
<%= f.label :display_order %>
<%= f.text_field :display_order, class: 'form-control' %>
<% cs = options_for_select(controls, f.object.selection_type) %>
<%= f.label :selection_type %>
<%= f.select :selection_type, cs, class: 'form-control' %>
<table class='table'>
<thead>
<tr>
<th>Category</th>
<th>Description</th>
<th>Display Order</th>
<th>Selection Type</th>
</tr>
</thead>
<tbody class="procedures">
<%= f.fields_for :procedures do |procedure| %>
<%= render 'procedure_fields', f: procedure %>
<% end %>
</tbody>
</table>
<%= link_to_add_association 'Add Skill', f, :procedures,
data: { association_insertion_node: '.procedures', association_insertion_method: :append } %>
<br><br>
<%= link_to_remove_association "Remove Category", f %>
</div>
Finally, here is my partial for rendering Procedures:
<tr class="nested-fields">
<td><%= f.text_field :skill, class: 'form-control' %></td>
<td><%= f.text_field :description, class: 'form-control' %></td>
<td><%= f.text_field :display_order, class: 'form-control' %></td>
<td><%= link_to_remove_association "Remove Skill", f %></td>
</tr>
Thank you for having a look.
I'm guessing you have .procedures under each of your Category sections. In which case, you're appending to both instances of the .procedures class.
You need to create a unique identifier for each Category section (e.g., #procedure-category-6 where 6 is assigned dynamically) and then use #procedure-category-6 .procedures for targeting your insertion.

Rails 4 How to display belongs_to record in a list

so please bear with me :)
group.rb
class Group < ActiveRecord::Base
has_many :categories, dependent: :destroy
validates :name, :presence => true, :uniqueness => { :case_sensitive => false }
validates :content, :presence => true
end
category.rb
class Category < ActiveRecord::Base
belongs_to :group
validates :name, :presence => true, :uniqueness => { :case_sensitive => false }
validates :content, :presence => true
validates :group_id, :presence => true
end
app/views/categories/index.html.erb
<% #categories.each do |category| %>
<tr>
<td><%= category.id %></td>
<td>
<%= link_to category.name, admin_category_path(category) %>
</td>
<td><%= ***[GROUP WHERE CURRENT CATEGORY BELONGS TO]*** %></td>
<td>
<%= link_to admin_category_path(category), class: "btn btn-info btn-xs" do %>
<i class="fa fa-search"></i>
<% end %>
<%= link_to edit_admin_category_path(category), class: "btn btn-primary btn-xs" do %>
<i class="fa fa-pencil"></i>
<% end %>
<%= link_to admin_category_path(category), method: :delete, data: { confirm: 'Are you sure?' }, class: "btn btn-danger btn-xs" do %>
<i class="fa fa-trash-o"></i>
<% end %>
</td>
</tr>
<% end %>
My question is: how to display a group belongs_to this categories?
It's simple, just write:
<td><%= category.group %></td>
Or
<td><%= category.group.name %></td>
One good idea is to define the function "to_s" for your classes.
For example
group.rb
class Group < ActiveRecord::Base
def to_s
name
end
That way Rails will automatically output the name for the group when printing the group meaning that
<td><%= category.group %></td>
and
<td><%= category.group.name %></td>
Will output the same information.
Use <%= category.group.name %> to display a group belongs_to this categories.

How to change my boolean output to a string value in ruby

I have a form where my user enters a person in reply to a wedding invite. They enter a name, menu choice, and select: attending - Yes / No - I then have a count on the true and false amounts with labels so the user can see how many people are attending or not attending.
My problem is in the table itself. Where the RSVP column sits, i have at moment just got 'true' or 'false'. Is there anyway in Ruby i can change this to be a string value for my index.html.erb?
Index
<% #replies.each do |reply| %>
<tr>
<td><%= reply.name %></td>
<td><%= reply.menu %></td>
<td><%= reply.rsvp %></td>
<td><%= link_to 'Show', reply, class: "btn" %></td>
<td><%= link_to 'Edit', edit_reply_path(reply), class: "btn" %></td>
<td><%= link_to 'Delete', reply, method: :delete, data: { confirm: 'Are you sure?' }, class: "btn btn-danger" %></td>
<td><%= reply.user.full_name %></td>
</tr>
<% end %>
reply.rb
class Reply < ActiveRecord::Base
attr_accessible :menu, :name, :rsvp, :user_id
belongs_to :user
def self.find_attending
Reply.where(:rsvp => "true").count
end
def self.find_not_attending
Reply.where(:rsvp => "false").count
end
end
_form.html.erb
<%= f.input :user_id, collection: User.all, label_method: :full_name, :label => 'Added By' %>
<%= f.input :name, :label => 'Person(s) Name' %>
<%= f.input :menu, :label => 'Menu Choice' %>
<%= f.collection_radio_buttons :rsvp, [[true, 'Attending'] ,[false, 'Not Attending']], :first, :last %>
db
class CreateReplies < ActiveRecord::Migration
def change
create_table :replies do |t|
t.string :name
t.text :menu
t.boolean :rsvp, :default => false
t.timestamps
end
end
end
I'm very new to Ruby, any pointers would be appreciated. Many thanks.
How about "#{reply.rsvp}"? Seems to be cleaner, doesn't it?
Just use a ternary:
reply.rsvp ? "true" : "false"
Replace "true" and "false" by whatever strings you want to display.

Resources