rails 4 def to_param with 2 models - ruby-on-rails

I came accross something strange when trying to create friendly URLs.
I have an item model which has:
def to_param
"#{id}-#{name}".parameterize
end
This makes my item URLs contain the "ID" and "name" just fine:
www.domain.com/items/ID-name
I also have a category model (item belongs to category and user models) where I have the same def to_param as above but the category URLs stay "unfriendly" no "name" included:
domain.com/categories/ID
I have name column in category table and it has values.
I also use ancestry for the category model. Maybe has_ancestry is causing the issue?
I tried below but no luck:
def to_param
[id, name.parameterize].join("-")
end
Thanks for any advice!

Papirtiger's comment lead me to the solution.
The problem was I had links like:
<% #category.children.in_groups_of(4, false) do |childs| %>
<tr>
<% for categories in childs %>
<td>
<%= link_to "../categories/#{categories.id}" do %><%= categories.name %><% end %></td>
<% end %>
</tr>
Beginners solution. :)
Removed the ugly part and now it works:
<% #category.children.in_groups_of(4, false) do |childs| %>
<tr>
<% for categories in childs %>
<td><%= link_to categories do %><%= categories.name %><% end %> (<%= Item.where(:category_id => categories.id).count %>)</td>
<% end %>
</tr>

Related

Displaying has and belongs to many associations in index

Hey I'm new to Rails and all this so bear with me, thanks!
I have two models:
class User < ApplicationRecord
has_and_belongs_to_many :sports
end
class Sport < ApplicationRecord
has_and_belongs_to_many :users
end
My users have a few different sports that they can choose each. I'm simply trying to display all users in a table, along with which sports they do. However.. the only way I've managed to get anything without an error is by using current_user as shown below. I've been looking how to do this for hours... I know it's going to be stupidly simple but I just can't figure it out or even know how to go in the right direction.
# users_controller.rb
def index
#users = User.all
#sports = current_user.sports
end
# users/index.html.erb
<% #users.each do |user| %>
<tr>
<td><%= link_to user.name, user %></td>
<td><%= link_to user.email, user %></td>
<% #sports.each do |s| %>
<td><%= s.name %></td>
<% end %>
</tr>
<% end %>
That's my current code but obviously this shows only the signed in users associations and repeats it for the other users like this:
<table>
<tr>
<th>Name</th>
<th>Sport 1:</th>
<th>2:</th>
</tr>
<tr>
<td>User 1 (current_user)</td>
<td>Football</td>
<td>Running</td>
</tr>
<tr>
<td>User 2</td>
<td>Football (User 1's Sports)</td>
<td>Running </td>
</tr>
</table>
Thanks in advance.
You can try using the following and deleting #sports = current_user.sports:
<% user.sports.each do |s| %>
<td><%= s.name %></td>
<% end %>
using user.sports while looping through each of the user will lead to N+1 queries on your database. You can change your controller method to something like
def index
#users = User.all.eager_load(:sports)
end
and then in html
<% user.sports.each do |s| %>
<td><%= s.name %></td>
<% end %>
This will load users along with left_outer_join on sports table and this will save to lot of extra queries on your database.
For Info you can refer this good blog.
Thanks

Generate attendance view/form in rails for all students

I am new to Rails and I am struggling on something which sounds easy but can not get it to work. I have two models Students and Attendances.
Student model:
name lastname classroom_id
Attendance model:
present:boolean absent:boolean halfday:boolean attnd_date:date student_id
Students has_many :attendances and attendance belongs_to :student.
I can make an entry for individual student and take their attendance however I want to generate a view where I show all the students (or show all students for a given classroom) and next to each student name I would like to show the three checkboxes so that I can mark who is present and absent in one go rather than one by one and submit the form.
Any help here is much appreciated. Using Rails 4 and ruby 2.2.0
Thanks
You can make an edit action, where you will find the classroom for which you want to mark attendances.
class AttendancesController < ApplicationController
def edit
#classroom = Classroom.find(<classroom-id>)
end
def update
end
end
In your view edit.html.erb
<%= form_for(#classroom, url: '/attendances/:id', method: :put) do |f| %>
<table>
<%- #classroom.students.each do |student| %>
<tr>
<td><%= student.name %></td>
<td><%= checkbox_tag "attendances[#{student.id}][present]" %></td>
<td><%= checkbox_tag "attendances[#{student.id}][absent]" %></td>
<td><%= checkbox_tag "attendances[#{student.id}][halfday]" %></td>
</tr>
<% end %>
</table>
<%= f.submit %>
<% end %>
This way, when you submit the form, you will receive these params in your update action:
`{ attendances: { '1' => { present: false, absent: true, halfday: false }, '2' => { present: true, absent: false, halfday: false }, ... } }`.
Then you can write logic in your action to save these details to database.
Note: This is kind of pseudo code. Please check the syntax and options for different html tags.
Thanks to #Jagdeep Singh for getting me up and running. I have now made the process more simple so I can get my head around. I just want to get the list of all students and create their attendances.
My view:
<% #students = Student.all %>
<%= form_for(:attendances, url: '/admin/attendances/') do |f| %>
<table>
<%= #today %>
<th>Name</th><th>Present</th><th>Absent</th><th>halfday</th>
<%- #students.each do |student| %>
<tr>
<td><%= student.first_name %></td>
<td><%= check_box_tag "attendances[#{student.id}][present]" %></td>
<td><%= check_box_tag "attendances[#{student.id}][absent]" %></td>
<td><%= check_box_tag "attendances[#{student.id}][halfday]" %></td>
</tr>
<% end %>
</table>
<%= f.submit %>
<% end %>
when I click on create attendance button it just creates just one with record with all default params and.
I am sorry I am still learning but once I get my head around on how I can create attendances for all 10 students i have in one go.

Ordering by date in Ruby on Rails

I am iterating over a set of objects in Ruby on Rails like so :
<% #subject.Association.each do |horse| %>
<tr>
<td>
<%= horse['Name'].to_s %>
<%= horse['Size'] %>
</td>
</tr>
<% end %>
The horse object has a date field, called dateRode.
I would like to order by this field.
I am not a ruby developer, but I tried a number of ways to do this resulting in only syntax errors e.g
<% subject.association.each do |horse|-> { order by "dateRode" DESC } %>
How can I do this in my code without editing ActiveRecords etc?
You can order collection with order method like this:
<% #subject.Association.order(dateRode: :desc).each do |horse| %>
<tr>
<td>
<%= horse['Name'].to_s %>
<%= horse['Size'] %>
</td>
</tr>
<% end %>
Try to replace this:
<% #subject.Association.each do |horse| %>
with
<% #subject.Association.order(dateRode: :desc).each do |horse| %>
Hoping that it would help you.
<% subject.association.each do |horse|-> { order by "dateRode" DESC } %>
The above is a mix of erb and sql which isnt going to work.
The best way to do it is to create a scope in the model which is called by the controller.
model
def self.order_by_date_rode
Model.includes(:association).order("associations.dateRode desc")
end
where Model is the name of your model and association is the name of the association you want to order by.
controller method
def some_method
#subject = Model.order_by_date_rode
end
A less recommended way is to do the sorting in the view
<% #subject.Association.order(dateRode: :desc).each do |horse| %>
the another way is that you can set a default scope for ordering of the association model like below
class Association < ActiveRecord::Base
default_scope { order('dateRode DESC') }
end
so when you do <% #subject.Association it will automatically sort

How to display all has_many items in index view?

I have two models, a calculation name and a different table with a bunch of calculations that go along with it. I have successfully established a one to many relationship (one name has many states) so that when I display calculation variables in my name/show view it works perfectly:
names/show view
<p><%= #name.calc_name %></p>
<% #name.states.each do |state| %>
<p><%= state.orbital_subset %></p>
<% end %>
I would, however like to display variables in my state value on the index page of names. Currently, I have a nice list of each name but creating an inner loop that loops through the states doesn't seem to work well. This works great too:
names/index view
<% #names.each do |name| %>
<tr>
<td><%= name.calc_name %></td>
</tr>
<% end %>
The best solution I found online is of this format which does not work:
<% #names.states.each do |state| %>
<p><%= state.orbital_subset %></p>
<% end %>
Should I be nesting two do loops on the index page since I am looping both through all of the names and through all of the states? Here are my models:
class Name < ActiveRecord::Base
has_many :states
end
class State < ActiveRecord::Base
belongs_to :name
end
The error that I get when I view names index is:
NoMethodError in Names#index
<% #names.each do |name| %>
<% name.states.each do |state| %>
<td><%= state.orbital_subset %></td>
<% end %>
<% end %>

Ruby on Rails - How to combine display Search results in the View

I have Search controller that searches 2 models - Posts and Categories. The search works, however I am unable to display results in the View correctly - I can't get category names to show up.
I am very confused and frustrated at this point and hope to find some help!
I'm pretty sure (99% sure) the problem is in the View somewhere, because I can get results to display through render inspect thingy.
SearchController.rb
class SearchController < ApplicationController
def index
#posts = Post.search(params[:search])
#categories = Category.search(params[:search])
# combine the results
#results = #posts + #categories
#results.uniq # may be necessary to remove duplicates
end
end
index.html.erb (views/search)
<%= render 'posts/posts', :posts => #posts %>
_posts.html.erb (view/posts)
<h1>Listing posts</h1>
<table>
<tr>
<th>Name</th>
<th>Category</th>
<th>Description</th>
<th>Flag</th>
</tr>
<% if posts %>
<% posts.each do |post| %>
<tr>
<td><%= post.name %></td>
<td><%= post.category.name %></td>
<td><%= post.description %></td>
<td><%= post.flag %></td>
</tr>
<% end %>
<% else %>
<tr><td>No posts</td></tr>
<% end %>
</table>
I can get posts that match the search to display, but I can't display categories. How can I do this? Any help highly appreciated!! Thank you.
If you are using a search backend like sunspot solr then you would be able to combine the searches like
#search = Sunspot.search [User, Company] do
fulltext params[:search]
end
#results = #search.results
And then return the necessary values. In this example, it's showing where you can retrieve the class of the action (controller_name) may not work depending on which controller the results are returned in.
<% #results.each do |result| %>
<% case result.class.to_s %>
<% when "Company" %>
<li><%= "Company: #{result.name}" %></li>
<% when "User" %>
<li><%= "User: #{result.username}" %></li>
<% end %>
<% end %>
The answer (I include all the things I changed to make it work + few files that I didn't change but that have to be there), or How to make simple search for multiple models:
SearchController.rb
class SearchController < ApplicationController
def index
#posts = Post.search(params[:search])
end
end
post.rb
class Post < ActiveRecord::Base
attr_accessible :category_id :name :description :flag
belongs_to :category
def self.search(search)
if search
find(:all, :joins => :category, :conditions => ['posts.equipment LIKE ? OR posts.description LIKE ? or categories.name like ?', "%#{search}%", "%#{search}%", "%#{search}%"])
else
find(:all)
end
end
search/index.html.erb
<%= render 'posts/posts', :posts => #posts %>
I added 2 files _post.html.erb and _category.html.erb. They are similar, this is _post.html.erb:
post: <%= post.name %>
(This might not be necessary in some cases or for some models. I can search a third model without this file in its' views. However the third model doesn't have file like _posts.html.erb either).
Finally, _posts.html.erb remains the same:
...
<% if posts %>
<% posts.each do |post| %>
<tr>
<td><%= post.name %></td>
<td><%= post.category.name %></td>
<td><%= post.description %></td>
<td><%= post.flag %></td>
</tr>
<% end %>
<% else %>
<tr><td>No posts</td></tr>
<% end %>
...
This works now. Can add new models to the search easily. The only other thing needed for the search is input field.

Resources