The relation is that a user has many treatments and a treatment belong to user, one-to-many.
Now i want to print out all the users that have this particular treatment
Inside my treatments show view i have this double loop
<% User.all do |user| %>
<%= user.treatments.each do |t| %>
<% if (t.id).to_i == (#treatment.id).to_i %>
<%= link_to user.name, user_path(user) %><br />
<% end %>
<% end %>
<% end %>
if i change <% User.all do |user| %> to <%= User.all do |user| %> it prints out everything in my users table
can you guys spot why im not getting any users ?
i put a message in the beginning of the inner loop and it didnt display either, guess the problem is there but im not seeing it
.all returns an array. Array doesn't accept a block. Most likely, you want to do .each but forgot to write it. Try this:
<% User.all.each do |user| %>
but a better way is to not iterate all users like this, but get the correct list from the database directly.
Related
Say I am displaying all of the users their posts as shown below.
<% #users do |user| %>
<div><%= user.name %> : </div>
<% user.posts.each do |post| %>
<div><%= post.title %></div>
<% end %>
<% end %>
Is it better to load the posts (specifically for database speed) beforehand in the controller?
#users = User.includes(:posts)
or is it better to just fetch the users and load the post in the view?
#users = User.all
When you iterate through a collection and access a child assocations this creates what is called a N+1 query issue where each record will create a separate database query.
If a single request ends up using 100 database queries your server will grind to a halt in no time.
<% #users do |user| %>
<div><%= user.name %> : </div>
<!-- This line will create a N+1 query -->
<% user.posts.each do |post| %>
<div><%= post.title %></div>
<% end %>
<% end %>
So yes - preloading associations is necessary to build applications that scale (or even work). ActiveRecord provides several methods such as .includes, .preload, .eager_load, .join and .left_outer_joins (Rails 5) that each give different results and are good for different use cases.
I'm new to rails and I'm trying to build a view that will list the parents and related children
Ex:
Passport has many Visas
I want to list information about the passport and the visas that the passport has.
So I have
<% #passport_list.each do |passport| %>
# passportFields
<% passport.visas.each do |visa| %>
<%= t.text_field :visa_type %>
<% end %>
<% end %>
I'm getting the error
undefined method `visa_type' for #Passport:0x000000091b8b28
It looks like rails is trying to find the property visa_type for passport, instead of in visa. How does the scope work within each? Can I force it to access visa_type from visa?
I think you're looking for the fields_for form helper. This will allow you to create fields for the relevant visa attributes. Replace your code sample with the following, and you should be all set.
<% #passport_list.each do |passport| %>
# passportFields
<% t.fields_for :visas do |visa_fields| %>
<%= visa_fields.text_field :visa_type %>
<% end %>
<% end %>
You can also iterate over the list as follows:
<% #passport_list.each do |passport| %>
# passportFields
<% passport.visas.each do |visa| %>
<% t.fields_for :visas do |visa_fields| %>
<%= visa_fields.text_field :visa_type %>
<% end %>
<% end %>
<% end %>
For more information on fields_for, check out the link I added above, and to customize further for your use case, check out the "One-to-many" section.
IMO you should always handle the null case of an object.
Something like this if you use rails (present? is a Rails function)...
<% if #passport_list.present? %>
<% #passport_list.each do |passport| %>
passportFields
<% passport.visas.each do |visa| %>
<%= t.text_field :visa_type %>
<%end%>
<%end%>
<% else %>
<p>Nothing to see here</p>
<% end %>
However if your #passport_list is backed by an ActiveRecord Query, you can handle this in the model/helper/controller by returning the .none query on the model. Note that this differs from an empty array because it is an ActiveRecord Scope, so you can chain AR queries onto it
# scope on AR model
def self.awesomeville
where(country_of_origin: "awesomeville")
end
# method queried in controller
#passport_list = Passport.all
if #passport_list.present?
#passport_list
else
Passport.none
end
# additional filtering in view is now possible without fear of NoMethodError
#passport_list.awesomeville
Whereas a ruby Array would raise an error as it would respond to the Array methods.
I have this block in my views:
<% video.members.each do |p| %>
<% if p.id == current_user.id %>
<%= "paid" %>
<% end %>
<% end %>
Basically I'm trying to work out if a member has paid for a video based on whether the id's match.
Maybe this a really bad way of doing it, which case I'd be happy to try and different method.
Assuming it is an ok way of checking this, how could I write a similar statement but as a helper method? I've tried, but it seems you can't write the same logic in helpers as the block just spits out the full array and not the id, meaning it doesn't work.
You should do this instead:
<% if video.members.exists?(id: current_user.id) %>
<%= 'Paid' %>
<% end %>
This will generate a single query to test if the video has been paid by the current_user ;-)
In a helper:
# application_helper.rb
def display_paid_or_not(video)
return '' if video.blank? # similar to .nil?
video.members.exists?(id: current_user.id) ? 'Paid' : ''
end
# in view
<%= display_paid_or_not(video) %>
Hope this helps!
Is it possible to call the include? function on a whole table, like this?
<% #user.games.each do |g|
##latestround = g.rounds.order('created_at DESC').first
%>
<% if ##latestround.submittedpictures.isFinalPicture.include?(true) %>
<p>FinalPicture has been played!</p>
<% end %>
<% end %>
The problem i'm getting is that It only works when I put a block on submittedpictures and then loop through each record of this table. However I want to look through the whole table in one go and see if the column 'isFinalPicture' includes a value with 'false'.
Any ideas?
The following snippet works but its not the way i want it (I would get more lines if the round happens to have more 'true' FinalPictures)
<% ##latestround.submittedpictures.each do |s| %>
<% if s.isFinalPicture == true %>
<p>Final Picture has been played!</p>
<% end %>
<% end %>
You could make a scope for it like
class SubmitedPricture << ActiveRecord::Base
scope :final_pictures, where('isFinalPricture = ?', true)
end
then you could see if there is any with only one query
latestround.submittedpictures.final_pictures.any?
Also you should follow the conventions of Rails in naming your Models and everything else. Like submittedpictures should be submitted_pictures
Sorry if the title is not enough to understand what i am asking about.
I am rails developer and i used multiple lines of <% %> in my views but now i realized that it's not best practice so i came here and like to you all excellent guys what is the correct way in ROR?
For example if i required to something like following
<% user =User.all %>
<% name= [] %>
<% count = 0 %>
<% for user in users %>
<% name << user.name %>
<% count+=1%>
<% end %>
Can i do it as follows ?
<% user =User.all
name= []
count = 0
for user in users
name << user.name
count+=1
end
%>
I know better way of collecting element from array But above is just example.
But my question is, is it possible and if yes which is the correct way?
I think the correct way is something totally different: move logic out of views.
This blog post explains what I mean.
in start and end must has '<%' or '%>'
Like:
<% users = User.all
name= []
count = 0
for user in users
count+=1
end %>
Using just a single pair of tags per code block is certainly preferable if only because it makes the output smaller.
The code should really rather look like
<% names = User.all.map(&:name) %>
Note that "count" can be obtained via names.size.
If you need to mix <% and <%= you need to switch:
<% for user in User.all %>
<%= user.name %></br>
<% end %>