List database entry with ID in view - ruby-on-rails

I found it difficult to title this question. It is easier if you see the situation:
by having this in my view
<% #scrapbook.scrapbook_entries.each do |d|%>
<%= d.recipe_id %>
<% end %>
I am given a list of recipe id's (3 of them) that are in the scrapbook_entries database table.
358 358 341
What I want to do is use these ID's and search the recipe table for all the information linked to them.
E.g. Display #recipe.name with ID 358.
Is there an easy way to do this in the view? Let me know if I am not making sense

If I understand you well, you can immediately put something like
= d.recipe.name
Behind the scenes, this will use your recipe id to look up the correct record, then take the name atttribute of this record

Try this:
<% #scrapbook.scrapbook_entries.each do |d|%>
<%= d.recipe_id %>
<%= d.recipe ? d.recipe.name : '' %>
<% end %>

If you have the relationship defined on the ScrapbookEntry model you can get the recipe instance and access any of its attributes.
class ScrapbookEntry < ActiveRecord::Base
belongs_to :recipe
end
<% #scrapbook.scrapbook_entries.each do |d|%>
<%= d.recipe.name %>
<% end %>

you can add a delegate in your scrabook_entry
delegate :name, :to => :recipe
than in your view
d.name

Related

Rails 5.2 each statement without duplicates values

<% Schedule.all.each do |schedule| %>
<%= link_to schedule.county, events_path(County: schedule.county) %>
Displays duplicates in the Schedule table
I've tried all below without luck in displaying no duplicates.
<% Schedule.all.each.uniq do |schedule| %>
<% Schedule.distinct.pluck(:county) do |schedule| %>
<% Schedule.distinct.each.pluck(:county) do |schedule| %>
They display nothing for some reason.
Edit:
Associations --
Event has_many :schedules, inverse_of: :event
Schedule belongs_to :event
So the original each block does bring in what I want but grabs the county for each schedule in the database. This results in duplicate county listings. I'm trying to remove these duplicates which I presumed was simple enough by adding a uniq method to the statement but looks like it requires joins. Thanks.
It depends on the association between schedule and country model. Assuming Schedule belongs to country
<% Schedule.joins(country).select(:country).distinct.each do |schedule| %>
<%= link_to schedule.county, events_path(County: schedule.county) %>
<% end %>
<% Schedule.select(:county).distinct.each do |schedule| %>
So looks like I didn't need a join. It was more just a select and then use distinct method which works. Thanks #Tacyons for putting me in the right direction.

Array of checkboxes in Rails

There is 'FoodType' model which are describes types of food in restaurants. I need to make view for creating a new restaurant, and I need to have list of checkboxes in order to allow user to setup types of food for each restaurant. I want to have something like this:
<% FoodType.all.each do |food_type| %>
...
<div class="row">
<%= f.check_box :food_types[0] %>
</div>
...
<% end %>
I want to have parameters like params[restaurant][food_types][0] = true in order to make some actions after creating. Please, tell me, how can I do it? Thanks in advance.
Presumably you have a join table which joins restaurants and food types? Let's say that you have one called restaurant_food_types (with a model RestaurantFoodType), which has restaurant_id and food_type_id?
You will then have this association in restaurants:
Restaurant < ActiveRecord::Base
has_many :restaurant_food_types
has_many :food_types, :through => :restaurant_food_types
This will give you the method .food_type_ids which you can call on a restaurant to set the joins. It's this method that you should hook into in your form: it expects an array of ids, so you need to set up an array-style parameter (one where the name ends in []) You may need to use check_box_tag rather than .check_box, to access an array-style parameter name: i would do this:
<% form_for #restaurant do |f| %>
<% FoodType.all.each do |food_type| %>
...
<div class="row">
<%= check_box_tag "restaurant[food_type_ids][]", food_type.id, #restaurant.food_type_ids.include?(food_type.id) %><%= food_type.name %>
</div>
...
<% end %>
<%= f.submit "Save" %>
<% end %>
Like i say i'm using a check_box_tag here but there might be a nicer way to hook into the food_type_ids method.

How to display a template for empty tables?

I have the following model
class User < ActiveRecord::Base
has_many :collabos
has_many :files
end
I want to display a conditional partial so the current_user can create a collabo or a file, when these models are empty?
Here's my first attempt, but it doesn't work well.
<% if current_user.files.empty? || current_user.collabos.empty? %>
<%= "create a file/collabo" %>
<% else %>
<%= yield %>
<% end %>
What's the best way to go for this kind of issue?
I think the picture below is better to show you the kind of behaviour I want to implement
You need and instead of or :
<% if current_user.files.empty? and current_user.collabos.empty? %>
However, it is always a nice idea to create User instance methods like :
def has_files?
files.empty? ? false : true
end
so that it becomes :
<% if current_user.has_files? and current_user.has_collabos? %>
(and you can always create a has_files_and_collabos method as well, if it's reusable code)

Rails: Cutting Down Code

I know that I might have too much logic in my view, so I'm wondering how I can include it in my controller:
Controller:
def purchasers
#deal = Deal.find(params[:id])
#pl = #deal.purchases
end
View:
<% title "List Of Purchases" %>
Total Purchases: <%= #pl.count %><BR><BR>
<%
#pl.each do |p|
u = User.find(p.user_id)
%>
<%= u.email %><BR>
<%
end
%>
I'd suggest that you remove the call to User.find inside the view code.
It looks like you're looking up the user from the user_id stored in the purchase. Why not in the model use:
class Purchase < ActiveRecord::Base
belongs_to :user
...
end
And then in the view code:
<% #pl.each do |purchase| %>
<%= purchase.user.email %><BR>
<% end %>
Hope this helps.
It looks like you might not have set up your associations correctly in your Purchases and Users models. Instead of doing u = User.find(p.user_id) you should be able to write p.user.email, assuming that each Purchase belongs_to :user.
if your Purchase model belongs to User model, you don't need to find User with User.find.
if not, belong your Purchase model to User model then
<% #pl.each do |p| %>
<%= p.user.email %>
<% end %>
Its also worth noting the following can be improved to make use of Rails' skills when it comoes to caching collections:
<%= #pl.count %>
to
<%= #pl.size %>
The size method will return the number of purchases but won't load the objects into memory again as they have already been looked up in the controller.

How can I display a list of three different Models sortable by the same :attribute in rails?

I have a Campaign model which has_many Calls, Emails, and Letters.
For now, these are each a separate Model with different controllers and actions (although I would like to start to think of ways to collapse them once the models and actions stabilize).
They do share two attributes at least: :days and :title
I would like a way to represent all the Calls, Emails, and Letters that belong_to a specific Campaign as a sortable collection (sortable by :days), in a way that outputs the model name and the path_to() for each.
For example (I know the below is not correct, but it represents the kind of output/format I've been trying to do:
#campaign_events.each do |campaign_event|
<%= campaign_event.model_name %>
<%= link_to campaign_event.title, #{model_name}_path(campaign_event) %>
end
Thanks so much. BTW, if this matters, I would then want to make the :days attribute editable_in_place.
Here is what I've got working, but want some additional insights
module CampaignsHelper
def campaign_events
return (#campaign.calls + #campaign.emails + #campaign.letters).sort{|a,b| a.days <=> b.days}
end
end
In the VIEW:
<% #campaign_events = campaign_events %>
<% #campaign_events.each do |campaign_event| %>
<% model_name = campaign_event.class.name.tableize.singularize %>
<p>
<%= link_to campaign_event.title, send("#{model_name}_path", campaign_event) %>
<%= campaign_event.days %>
</p>
<% end %>
Like this?
# controller
#campaign = Campaign.find(params[:id])
#campaign_events = (#campaign.calls + #campaign.emails + #campaign.letters).sort{|a,b| a.days <=> b.days}
# view
#campaign_events.each do |campaign_event|
<%= campaign_event.model_name %>
<%= link_to campaign_event.title, #{model_name}_path(campaign_event) %>
end
In controller you find all campaign events and sort it by days field

Resources