Array of checkboxes in Rails - ruby-on-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.

Related

How to use models from associations in views with HABTM

I have a #friend model that has_and_belongs_to_many #interests and vice versa. Each interest has a name:string. How do I show all the interests by their name next to each friend?
I tried
friend.interests.count
which shows the correct number, but for
friend.interests.first
the result is
#<Interest:0x00007f959e103250>
How do I display the name of this interest from the database in a view?
<%= friend.interests.count %>
<%= friend.interests.first %>
You can get the name of the interest, just by accessing the friend.interests.first.name. And for listing all the interests you can iterate and show the name of them.
<% friend.interests.each do |interest| %>
<%= interest.name %>
<% end %>
Just put the attribute after the object:
<%= friend.interests.first.name %>

Rails habtm checkboxes on create

Is possible to utilize the habtm checkboxes on create action?
because this:
<%= hidden_field_tag "product[size_ids][]", nil %>
<% Size.order(:size).each do |size| %>
<li> <%= check_box_tag "product[size_ids][]", size.id, Product.size_ids.include?(size.id), id: dom_id(size) %>
<%= label_tag dom_id(size), size.size %>
</li>
<% end %>
was on update and was working since was brought to create page rails spits out the
undefined method `size_ids' for #
so, have a way to utilize the habtm on a create action?
Since you're likely dealing with one item, you probably mean:
#product.sizes_ids
The Product model doesn't have a direct association with any sizes, it's only instances of it that do.
use collection check boxes getting all of the model with ids exemple:
<%=p.collection_check_boxes :size_ids, Size.all, :id, :size %>

Replace one model attribute by another in rails form

I am building a very simple movie review app with Rails, which does not have any authentication system.
The app has:
a User model (id, name, email), which has many Reviews and has many Comments
a Review model (id, title, image, content), which belongs to one User and has many Comments
a Comment model (id, content), which belongs to one User and belongs to one Review
Here is the _form.html.erb file for comments:
<%= bootstrap_form_for(#comment) do |f| %>
<% if #comment.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#comment.errors.count, "error") %> prohibited this comment from being saved:</h2>
<ul>
<% #comment.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.text_field :content %>
</div>
<div class="field">
<%= f.number_field :review_id %>
</div>
<div class="field">
<%= f.number_field :user_id %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
When adding/editing a comment, the user can chose the Review to which the comment will be attributed, thanks to:
<div class="field">
<%= f.number_field :review_id %>
</div>
which lets him chose between review ids.
Instead, I would like the user to be able to select the review title of the review he wants to comment upon.
I tried to modify the review model with a to_param method, but it did not solve the problem and actually created some other bugs in the app.
How can I solve the problem?
Further to ply's answer, what you have to remember is when you populate an object-based form, you're really taking a Model's attributes & populating them
form_for:
Typically, a form designed to create or update a resource reflects the
identity of the resource in several ways: (i) the url that the form is
sent to (the form element's action attribute) should result in a
request being routed to the appropriate controller action (with the
appropriate :id parameter in the case of an existing resource), (ii)
input fields should be named in such a way that in the controller
their values appear in the appropriate places within the params hash,
and (iii) for an existing record, when the form is initially
displayed, input fields corresponding to attributes of the resource
should show the current values of those attributes.
--
You are populating the Comment model object - this will have attributes defined in your database, such as body, title etc
One of the attributes in the Comment model is the review_id foreign_key
To the Comment model, it does not matter how review_id is passed to it; just that it's done. This is why it does not matter if you use a text_field to input the id directly, or if you use a select tag to help the user select the item they want
--
collection_select
<%= f.collection_select(:review_id, Review.all,
:id, :title,
{:prompt => 'Please select the review of this comment'}) %>
This will give you a select box where you can pick the review
--
Nested Route
A much better way to do this is to use a nested route, so you can set review_id from the parmas:
#config/routes.rb
resources :reviews do
resources :comments #-> /reviews/1/comments/new
end
#app/controllers/comments_controller.rb
def create
#comment = Comment.new(comment_params)
#comment.save
end
private
def comment_params
params.require(:comment).permit(:content).merge(review_id: params[:review_id])
end
Not sure if I follow, but could you just use a select tag here?
This assumes you have an instance variable named #reviews defined in your controller that will be available.
In this case #reviews could be something like Review.all
select_tag "review", options_from_collection_for_select(#reviews, "id", "title"), prompt: "Select a review"

How to get model objects in the form with rails check_box?

How do i get checkbox values in the form from the database? I want the form to bring the existing sub category name,and when i check the checkbox to select that particular category name and not create a new one.I have tried ryan bate's railscast but was no help to me. The realationship here is Category has_many SubCategories and SubCategory belongs_to Category.Thank you.
<%= form_for #category ,:url=>{:action =>"create"} do |f| %>
<%=f.text_field :category_name %>
<%= f.fields_for :sub_categories do |s| %>
<% #category.sub_categories.each do |sub|%>
<%=s.check_box "name",{},sub.id %> <!--need help here-->
<%end%>
<%end%>
<%=f.submit "submit"%>
<%end%>
Based on the exchange in the comments, it appears that you want to use the checkboxes to assign SubCategory objects to a Category object. If that's the case, you're association should be that a Category has_and_belongs_to_many :sub_categories. Then your form would look something like:
<%= form_for #category ,:url=>{:action =>"create"} do |f| %>
 <%=f.text_field :category_name %>
<% SubCategories.each do |sc| %>
<div>
<%= check_box_tag :sub_category_ids, sub_category_id, #category.sub_categories.include?(sc), :name => 'category[sub_category_ids][]' -%>
<%= label_tag :sub_category_ids, sc.name -%>
</div>
<% end -%>
<% end %>
Which will show a category form and then list all of the sub_categories that can be assigned or unassigned by checking the checkboxes.
You will also need a join table "categories_sub_categories" for this new association and logic (likely in your controller) to handle the actual assignment.
example for your category_controller.rb
def create
#category = Category.find(params[:id])
#use the checked sub_category_ids from the form to find and assign the sub_categories.
assigned_sub_categories = SubCategory.find(params[:category][:sub_category_ids]) rescue []
#category.sub_categories = assigned_sub_categories
if #category.save
…
else
…
end
end

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