Rails collection_check_boxes, Using two labels with one from an association - ruby-on-rails

I have an Available model with a date attribute, I also have a User model. A user has_many :availables and available belongs_to :user.
#dates is a collection of Available records. In the form I want to show both the date and the associated user name for that record. What I currently have is working though I can't click name to select the checkbox, is there a proper way to do this and style it via bootstrap?
= f.collection_check_boxes :col_ids, #dates, :id, :date do |b|
.field
.checkbox-inline
= b.check_box
= b.label
= b.object.user.name

What you want is a checkbox which is inside the label tag.
= f.collection_check_boxes :col_ids, #dates, :id, :date do |b|
.field
.checkbox-inline
= b.label do
= b.check_box
= b.text
= b.object.user.name
On a side note your model should be named Availablity which is a noun. Not the adverb form available (availables is not an english word).
A person may be available, but has many availabilities.
availability
plural avail·abil·i·ties
the quality or state of being available
an available person or
thing
http://www.merriam-webster.com/dictionary/availability
This is not a big deal but can give english speakers are real WTF moment when trying to understand your code.

Related

Simple Form - Multiple attributes in checkbox group

I have a User Model with the following attributes:
# full_time :boolean
# part_time :boolean
# contract :boolean
I would like to create a simple form checkboxes group for these attributes. From what I've been able to understand, the simple form api is meant to map to has_many & has_and_belongs_to_many associations, as follows:
f.collection_check_boxes :role_ids, Role.all, :id, :name
Is there a way to handle updating multiple attributes on the given model within the form's API guidelines? Or is this an indication that should I be modeling the data in a different way?
f.collection_check_boxes is a generic method for generating multiple checkboxes with arbitrary name/value, for a single attribute. The sample you gave is mentioned in the docs as a last one for this method, probably because f.association is way better for association attributes.
<%= f.association :role, Role.all %>
In case of your attributes, I don't think f.collection_check_boxes is applicable. If the attributes aren't mutually exclusive, then I don't see anything wrong - stick with them and just give each one a checkbox of it's own.
<%= f.input :full_time %>
<%= f.input :part_time %>
<%= f.input :contract %>
simple_form will detect their type and generate a checkbox for each. Use wrapper: false option, if you want to get rid of wrapper divs and group them more tightly.
If they were mutually exlusive, then an integer column and enum would be probably a better idea.

Creating a form for a has_and_belongs_to_many relationship

I've read through a lot of posts regarding this topic, but not one actually provides a good answer.
I have a class A and a class B who are related through a has_and_belongs_to_many relationship.
class A < ApplicationRecord
has_and_belongs_to_many :bs
end
class B < ApplicationRecord
has_and_belongs_to_many :as
end
What I need is a form for class A showing a selection field with all the instances of B to select. Also, when editing and instance of A, the form should present a list of the related instances of B and a way to mark them for removal.
I have tried creating the list of existing instances by providing a hidden field with the id for each instance of B. And I have created a selection field using the select_tag. The code looked something like that:
= form_for #a do |f|
.field
= f.label :name
= f.text_field :name
.field
- #a.bs.each_with_index do |b, i|
= b.name
= hidden_field_tag "a[b_ids][#{i}]", b.id
.field
= select_tag "a[b_ids][]", options_from_collection_for_select(#bs, "id", "name")
.actions
= f.submit 'Save'
This worked just fine when creating the new instance of A. But when I tried to edit it, there seems to be a problem making the execution fall back to using POST instead of PATCH. And since with there is now route for POST when editing/updating this obviously ended in an exception.
So I wonder if there is any clean way to create the form I need?

grouped_collection_select with different option_key_methods

I'm using grouped_collection_select with polymorphic associations to assign either a company or person to a task. The issue is that people have a first name and a last name, while a company just has a name. I would like to use a concatenation of :fname and lname as the option_key_method for the person group in the menu and I would like to use :name as the option_key_method for the company group in the menu.
I however haven't run across this in my Google investigation. As it stands, I'm using :email as the option_key_method because it's the most distinguishing field that's shared by the two models:
<%= f.grouped_collection_select :entity_id, [Company, Person], :all, :model_name, :to_global_id, :email %>
How might I set it up to make use of the two different kinds of name fields that are implemented by the two different models?
You can pass a lambda method to the option_key_method, which takes the object currently in hand Person or Group in your case and you can do the processing you want on it
Example:
<%= f.grouped_collection_select :entity_id, [Company, Person], :all, :model_name, :to_global_id, lambda {|company_or_person_object| company_or_person_object.instance_of? Company ? company_or_person_object.fname + company_or_person_object.lname : company_or_person_object.name} %>

Is there a way to get the `id` of a nested_form field helper element?

I am trying to create the for attribute for a label in a nested form (Using nested_form). Is there a way to get the id of a corresponding f.checkbox?
HAML:
= label_tag '???', "Set as On", class: primary_btn
= f.check_box :is_on
Additional Information:
The current Model structure is like Post has many Images with field is_on
So I would like to create a nested field group like:
<label class="primary_btn" for="post_images_attributes_0_is_on">Set as primary</label>
<input id="post_images_attributes_0_is_on" name="post[images_attributes][0][is_on]" style="display:none;" type="checkbox" value="1">
The trick is to use fields_for. It gives you a "scoped" form builder instance which creates inputs for the nested fields.
= form_for (:post) do |f|
# ... a bunch of fields
= f.fields_for :images do |builder|
= builder.label :is_on, "Set as primary"
= builder.check_box :is_on
However your solution has some real gotchas:
Every time you change the primary image you need to update all the post.images to ensure that only one image has the is_on flag.
You need to do primary_image = post.images.where(is_on: true)
It won't work if the image can belong to many posts.
A better solution is create a special relation to the primary image on Post.
class Post < ActiveRecord::Base
has_many :images
has_one :primary_image, class_name: 'Image'
end
This would store the primary image as an integer in posts.primary_image_id instead of as a boolean flag on images.
We can use collection_select to get select tag to display the primary image attribute.
= form_for (#post) do |f|
# ... a bunch of fields
= f.fields_for :images do |builder|
# ...
= f.collection_select(:primary_image, #post.images, :id, :name)
This admittedly is not really optimal from a user experience perspective. A solution which requires javascript would be to have a hidden field for :primary_image and update its value when the user clicks the checkbox. If you are unsure how to do this please create a new question since its out of the scope of your original question.

ruby on rails how to use FormOptionHelpers to create dynamic drop down list

I have checked some tutorials but I got confused by the parameters in this method
collection_select (object, attribute, collection, value_method, text_method, options = {}, html_options ={})
I have a map model includes: :area, :system, :file
and I want to read :area from database to a drop down list, and let user choose one
I already did #map = Map.all in the view
what the method should be?
especially the parameter "attribute". In a lot tutorials, people put "id" here. But I don't know what "id" is, and in my situation I don't need any other value, just the "area".
Im not exactly sure what you are asking here but if you are trying to make a dropdown selection for use in an html form will this example help you at all?
<% nations = {'United States of America' => 'USA', 'Canada' => 'Canada', 'Mexico' => 'Mexico', 'United Kingdom'=> 'UK'} %>
<% list = nations.sort %>
<%= f.select :country, list, %>
Here nations is a hash of countries then list becomes the sorted copy of that hash. An html dropdown is then created as a part of the form "f". ":country" is the part of the model that the data is connected to while list is the options to populate the dropdown with
It's not clear from your question what the model is that's being populated with the area.
Typically, collection_select is used between related models.
eg.
class Category < ActiveRecord::Base
has_many :products
end
class Product < ActiveRecord::Base
belongs_to :category
end
When selecting the 'category' for a product, your view would have something like:
<%= f.collection_select(:category_id, :id, Category.all, :name, include_blank: true) %>
What this does is specify the Product.category_id as the attribute being populated with the value of Category.id. The values come from the Category.all collection, and with Category.name being the item displayed in the select. The last (optional) parameter says to include a blank entry.
Something like the following is probably what you need:
<%= f.collection_select(:map_id, :id, #map, :area) %>
However, if the model you're trying to populate has an area attribute (instead of an ID linking to the map), you might need to use:
<%= f.collection_select(:area, :area, #map, :area) %>
This specifies that the area attribute of the receiving table will be populated with Map's area attribute, which is also being used as the "description" in the select.

Resources