Two collection_select that save as two different records - ruby-on-rails

I have this:
<%= f.collection_select :category_ids, Category.all, :id, :name, {} %>
inside my form and it creates the record no problem, however I'm lost on how to make more two or more records inside the same form, all the things I try either just create the one record or none at all. I found this solution, which I analyzed and was sure was gonna work (altough I don't really get on why it uses nil):
<%= f.fields_for :category_ids do |category| %>
<%= category.collection_select(nil, Category.all, :id, :name,
{include_blank: "---", selected: 0},
{id: :event_category_id_1}) %>
<%= category.collection_select(nil, Category.all, :id, :name,
{include_blank: "---", selected: 0},
{id: :event_category_id_2}) %>
<% end %>
but this time it creates no record at all.
Here are my models:
class Event < ApplicationRecord
has_many :categorizations
has_many :categories, through: :categorizations
accepts_nested_attributes_for :categorizations
end
class Category < ApplicationRecord
has_many :categorizations
has_many :events, through: :categorizations
end
class Categorization < ApplicationRecord
belongs_to :event
belongs_to :category
end

You want to assign more than one Category to your Model? Post your model so we can figure what's going wrong when storing it.
Adding multiple: true (and size: 5) will expand your select field and by holding ctrl/cmd you can select multiple entries.
<%= f.collection_select :category_ids, Category.all, :id, :name, {multiple: true, size: 5} %>

Related

How to acces foreign attributes in a select form in Rails?

If I have the models:
class Bloque < ApplicationRecord
belongs_to :temporada
end
class Temporada < ApplicationRecord
has_many :bloques
end
And the collection_select in a view:
<%= collection_select(:bloques, :id, Bloque.all, :id, :temporada, {}, {class: 'form-control', multiple: 'true'}) %>
I want the name of temporada in Bloque, as in :temporada_name, instead of plain :temporada in the collection_select. Because the list appears as:
and I want the name of the temporadas to show.
Use Module#delegate to delegate temporada_name to temporada.name.
class Bloque < ApplicationRecord
belongs_to :temporada
delegate :name, to: :temporada, prefix: true
end
<%= collection_select(:bloques, :id, Bloque.includes(:temporada).all, :id, :temporada_name, {}, {class: 'form-control', multiple: 'true'}) %>

Rails 4 collection_select ordering

I am trying to order my collection_select dropdown by name instead of the default ID.
I have searched for a way to do this in Rails 4 but haven't found the solution. My code is:
<%= f.collection_select(:material_id, Material.order('name ASC').all, :id, :name) %>
This still returns a list ordered by ID. The models I'm using are:
Glaze.rb
has_many :ingredients
has_many :materials, :through => :ingredients
Ingredients.rb
belongs_to :glaze
belongs_to :material
Material.rb
has_many :ingredients
has_many :glazes, :through => :ingredients
Try this one, It should work. Will be passed name and attribute value with c.id
<%= f.select :material_id, Material.order('name ASC').map {|c| [c.name, c.id] },
{prompt:"Choose Material"}, class: "form-control" %>

unable to make the model it belongs to also be one that can has_many

I'm struggling when it comes to having a joint table, which is also polymorphic and has many to many.
It's setup in a way that a question belongs to a company. A question can belong to a user, group or company through question_participants (polymorphic / joint).
Now I am able to save both users and groups but not company when they select that. I think it has to do with the confusion of it being the owner.
# ask question
class QuestionsController < ApplicationController
def new
#question = current_user.company.questions.new
end
private
def question_params
params.require(:question).permit(:name, :optional,
user_ids: [], group_ids: [])
end
# company users belong to
class Company < ActiveRecord::Base
has_many :questions
end
# questions created by admin
class Question < ActiveRecord::Base
belongs_to :company
has_many :question_participants
has_many :answers
has_many :users, through: :question_participants,
source: :questionable, source_type: 'User'
has_many :groups, through: :question_participants,
source: :questionable, source_type: 'Group'
has_many :companies, through: :question_participants,
source: :questionable, source_type: 'Company'
end
and the form field:
<%= form_for #question do |f| %>
<%= f.label :group_ids %>
<%= f.collection_select :group_ids, current_user.company.groups.order(:name), :id, :name, {},
{ multiple: true } %>
<%= f.label :user_ids %>
<%= f.collection_select :user_ids, current_user.company.users.order(:first_name), :id, :first_name, {},
{ multiple: true } %>
<%= f.label :name %>
<%= f.text_field :name, class: "form-control" %>
<%= f.submit class: "btn btn-success" %>
<% end %>
If the problem is just that companies is showing up twice as a field on the Question class, just change the has_many line at the bottom of the Question class to:
has_many :questionable_companies, through: :question_participants,
source: :questionable, source_type: 'Company'
If that works, great! Otherwise....
I don't know a lot about polymorphism, but from what I do know, here's what I think will work:
User, Group, and Company should have this line:
has_many :question_participants, as: questionable
Question should use scopes instead of the three lines you have. Try this:
has_many :questionable, through: :question_participants
Once you've gotten :questionable as a field on Question, then you can make scopes
scope :questionable_users, -> { where(questionable_type: :User) }
scope :questionable_groups, -> { where(questionable_type: :Group) }
scope :questionable_companies, -> { where(questionable_type: :Company) }
I put questionable_ before each scope just so that the Company associations wouldn't complain.
I forget exactly how scopes compare to a belongs_to but it's possible it may miss some functionality you want.

Rails has_many :through and collection_select with multiple

I have the following problem using a has_many :through many-to-many relation in a multi-select via collection_select :multiple => true. I have Suppliers who deliver many Ingredients which can be delivered by many Suppliers. Have a look:
The Ingredient model:
class Ingredient < ActiveRecord::Base
has_many :ingredient_suppliers
accepts_nested_attributes_for :ingredient_suppliers, :allow_destroy => true
has_many :suppliers, :through => :ingredient_suppliers
end
The Supplier model:
class Supplier < ActiveRecord::Base
has_many :ingredient_suppliers
has_many :ingredients, :through => :ingredient_suppliers
end
The relationship Entity:
class IngredientSupplier < ActiveRecord::Base
belongs_to :ingredient
belongs_to :supplier
end
And this is the form. Note that I could not get it to work without specifying the :name:
<%= form_for(#ingredient) do |f| %>
<%= f.fields_for :suppliers do |supplier_fields| %>
<%= supplier_fields.collection_select (:supplier_ids,
Supplier.all(:order=>"name ASC"),
:id, :name,
{:selected => #ingredient.supplier_ids,
:include_blank => true},
{:multiple => true,
:name => 'ingredient[supplier_ids]'}) %>
<% end %>
<% end %>
If I remove the :name, then I get this error message:
Supplier(#-617951108) expected, got Array(#-608411888)
Request
Parameters:
{"commit"=>"Anlegen",
"authenticity_token"=>"MuEYtngwThharmM1KaAbH8JD3bScXiDwj0ALMytxl7U=",
"_method"=>"put",
"utf8"=>"✓",
"id"=>"1",
"ingredient"=>{"name"=>"Ingredient 1",
"nr"=>"00100",
"unit"=>"kg",
"mol_per_unit"=>"2000,
00000",
"description"=>"",
"suppliers"=>{"supplier_ids"=>["1",
"2"]}}}
The problem now is, that the PUT parameters only contain one supplier_id instead of an array of supplier_ids:
"ingredient"=>{"name"=>"Rohstoff 3", "nr"=>"00300", "unit"=>"Stk.", "mol_per_unit"=>"0,00000", "description"=>"", "supplier_ids"=>"2"}
I've got the problem solved. In this case, using fields_for was the error. The solution is using a collection_select, like this:
<%= collection_select(:ingredient, :supplier_ids,
Supplier.all(:order=>"name ASC"),
:id, :name, {:selected => #ingredient.supplier_ids, :include_blank => true}, {:multiple => true}) %>

One to many relationship in ROR using Formtastic

following up with this topic:
(Rails) How to display child records (one-to-many) in their parent's form?
I am creating a category that may have many products. So, I use the Formtastic as user Chandra Patni suggested. But I find there is a problem when I added attr_accessible to the product.rb.
class Product < ActiveRecord::Base
validates_presence_of :title, :price
validates_numericality_of :price
validates_uniqueness_of :title
attr_accessible :category_id, :name
belongs_to :category
end
and this is the category.rb:
class Category < ActiveRecord::Base
attr_accessible :name
has_many :products
end
After I added the attr_accessible :category_id, :name , the validation gets crazy, no matter I type, it treats me as null in the text value. But after I remove the attr_accessible :category_id, :name all stuff works.
One more thing, in the products/new.html.erb , I created this to input the product information,
<% semantic_form_for #product do |f| %>
<% f.inputs do %>
<%= f.input :title %>
<%= f.input :price %>
<%= f.input :photoPath %>
<%= f.input :category %>
<% end %>
<%= f.buttons %>
<% end %>
But I find that it return the :category id instead of the category name. What should I do?
Thx in advanced.
You will need to add other attributes to attr_accessible for rails to perform mass assignment.
attr_accessible :category_id, :name, :title, :price, :photoPath
Rails will only do mass assignment for attributes specified in attr_accessible (white list) if you have one. It is necessary from security point of view. Rails also provides a way to blacklist mass assignments via attr_protected method.
You should see a drop down for category if you have name attribute in your Category model. See this and this.
class Category < ActiveRecord::Base
has_many :products
attr_accessible :name
end

Resources