Drop-Down-Menu for Many-to-Many relation in rails using nested attributes
In you products form you need to add this line...
<%= collection_select(:product, :supermarket_ids, SuperMarket.all, :id, :name, {}, { :multiple => true } )%>
You also shouldn't need to use an accepts_nested_attributes for this, the many to many association you already have set up should take care of the rest.
Passing in select menu into nested form's attributes
Instead of this line
=select("dish", "menu_id", Menu.all.collect {|r| [ r.name, r.id ] }, {:include_blank => 'Choose a Menu'})
use it with form object
=f.select("menu_id", Menu.all.collect {|r| [ r.name, r.id ] }, {:include_blank => 'Choose a Menu'})
I hope this will sort out your id problem as well as part of dishes attributes
Drop down menu with value from another model
You can use a collection select, first make sure your models are properly setup:
class Product
belongs_to :collection
end
class Collection
has_many :products
end
Then add the collection select to your view:
<%= collection_select(:product, :collection_id, Collection.all, :id, :name) %>
You can also read up on the documentation here.
Many-to-Many-to-Many relationship with need for another specific model
Here, I might have supply belong to origin instead of product.
Also, think about whether you need SpecificCombination. What operations are you going to do with it? Are you going to list all the SpecificCombinations in your database? Are you going to search to find a specific one? Are you going to create a new combination?
Then think if these operations can be done simply with the other classes?
class Supermarket < ActiveRecord::Base
has_many :supplies
has_many :origins, :through => :supplies
def self.choice
Supermarket.all.map { |supermarket| [ supermarket.name, supermarket.id ] }
end
end
end
class Supply < ActiveRecord::Base
belongs_to :origin
belongs_to :supermarket
end
class Origin < ActiveRecord::Base
belongs_to :supplies
belongs_to :brands
end
walmart = Supermarket.create(:name => "Walmart");
cornflakes = Product.create(:name => "Corn Flakes");
kellogs = Brand.create(:name => "Kellog's");
walmart.origins.create(:product_id => cornflakes, :brand_id = kellogs)
Many-to-Many-Relationship maybe needs polymorphic associations? Help needed for model creation
You probably want to have the many-to-many relationship between the supermarket and the detailed product. The detailed product would have a foreign key to the general product.
Let's say you name the general product model genus (plural: genera). [Feel free to find a better name.]
class Genus
has_many :products
end
class Brand
has_many :products
end
class Product
belongs_to :genus
belongs_to :brand
has_many :supplies
has_many :supermarkets, :through => :supplies
end
class Supply
belongs_to :product
belongs_to :supermarket
end
class Supermarket
has_many :supplies
has_many :products, :through => :supplies
end
Product Genus
Granny Smith Apple Apple
Golden Delicious Apple Apple
Braeburn Apple Apple
Macintosh Apple Apple
Kellog's Cornflakes Cornflakes
GM Cornflakes Cornflakes
Kellog's Rice Krispies Rice Krispies
You might also include a foreign key in Product to brand, to store Kellog's or General Mills.
Assigning id's from another table to input using nested forms in Rails 4
The reason a new record is created every time you submit a new staff member is because you don't actually let your controller know that the staff member's type could be an existing type. So now the question is, what is the best way to go about doing this EDIT THIS SENTENCE
Method #1: Choose staff member types in a multi-select
If you have a set number of types, you've already inserted them, and you don't need to change them, then you can use a multi-select. To do so, replace the below code in your code...
<%= f.fields_for :types, @staff.types do |types_form| %>
<%= types_form.label :department %>
<%= types_form.text_field :department %>
<% end %>
...with:
<%= f.collection_select :type_ids, Type.all, :id, :department,
{ selected: @staff.type_ids }, { multiple: true, size: Type.all.size } %>
And then, in your controller, change your staff_params
method to:
def staff_params
params.require(:staff).permit(:staff_name, :staff_email, type_ids: [])
end
Using this method, you'll be able to select multiple types for each staff member out of all possible types. Assuming you don't need to create a type when you create a staff member, I'd recommend going forward with this member.
You can also use checkboxes rather than a multi-select, but I won't cover that in this answer. You can read about check boxes here.
Method #2: Determine which types are new in your controller
If you'd like to keep the ability to type in a staff member's type, it'll be a bit trickier, but I think you can keep all of your logic in the create
method of your controller. Currently, in that method, you save a staff member as soon as you grab the parameters for it. What you can do first is check if any of the types passed are new (i.e. the staff member hasn't yet been associated to that type), and then if at least one is, check if each is an existing type. Update your create
method to read:
def create
@staff = Staff.assign_attributes(staff_params)
@staff.staff_types.each_with_index do |staff_type, index|
if (type = Type.find_by(department: staff_type.type.department)).present?
@staff.staff_type[index].assign_attribute(:id, type.id)
end
end
if @staff.save
flash[:success] = "Your account has been created successfully"
redirect_to staff_path(@staff)
else
render 'new'
end
end
I should note that there is probably a better way to do this, and hopefully this answer encourages someone to post a better one, but this answer should work for your purposes.
How to save 2 id in joint table for many-to-many relationship in rails 3.1
this is easier than you might think because it's handled automatically by ActiveRecord.
When you say "has_and_belongs_to_many", you're telling AR to associate those two models with a many-to-many relationship using the table, and for the most part you no longer need to worry about the join table. When you add an instance of Standard to an Rfq's list of standards, this will be done for you.
Here's an example:
rfq = Rfq.create
standard = Standard.create
rfq.standards << standard
We've created each of the objects, and the third line creates the connection, saving a new record in the rfqs_standards table with the proper ids. rqf.standards looks and acts like a normal array, but when you assign objects to it, ActiveRecord does the database work for you.
After creating the records, you could have also done:
standard.rfqs << rfq
You could also do both at the same time:
rfq = Rfq.create
standard rfq.standards.create
This created an rfq, then created a standard that is automatically connected to the rfq. You can do the same thing in reverse:
standard = Standard.create
rfq = standard.rfqs.create
I hope this helps!
UPDATE: Since you mentioned forms and automatic saving, read my article on nested attributes that shows how to implement that, including full code samples.
nested_form, collection_select, accepts_nested_attributes_for and fields_for, and adding records to a join table
Well. Here's how I did it.
Installed cocoon gem.
Finally got round to installing Haml, too,
I split out the new and update action, so the new form is just a quickie to get the id set, with the bare minimum of fields. Then users can edit it, and add contributors. Not actually bad from the user point of view as they can create an isbn quickly without having to fill in a bazillion fields.
isbns/new.html.haml
%td.main
= semantic_form_for @isbn do |f|
%h1 Create new ISBN
= render 'shared/error_messages', :object => f.object
= render 'fields', :f => f
%div#actions
= f.submit "Create"
isbns/_fields.html.haml
- f.inputs do
= f.input :istc_id, :as => :select, :collection => Istc.all
= f.input :descriptivedetail_titledetail_titleelement_titlewithoutprefix
%h3 Contributors
#tasks
= f.semantic_fields_for :linkers do |linker|
= render 'linker_fields', :f => linker
.links
= link_to_add_association 'add contributor', f, :linkers
-f.buttons do
= f.submit 'Save'
isbns/_linker_fields.html.haml
.nested-fields
= f.inputs do
= f.input :contributor_id, :label_method => :keynames, :as => :select, :collection => Contributor.all
= link_to_remove_association "remove contributor", f
Isbn.rb
has_many :linkers
has_many :contributors, :through => :linkers
accepts_nested_attributes_for :contributors, :allow_destroy => true
accepts_nested_attributes_for :linkers, :allow_destroy => true
contributor.rb
attr_accessible :linkers_attributes, :isbns_attributes
has_many :isbns, :through => :linkers
has_many :linkers
accepts_nested_attributes_for :linkers
linker.rb
belongs_to :contributor
belongs_to :isbn
accepts_nested_attributes_for :contributor
Results in
Started POST "/isbns/58" for 127.0.0.1 at 2011-06-09 12:34:14 +0100
Processing by IsbnsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"u0TszLESOnZlr4iEiBlVg6w9B5T+EH0dxJg/0E6PKuQ=", "isbn"=>{"istc_id"=>"360", "descriptivedetail_titledetail_titleelement_titlewithoutprefix"=>"thurs title", "linkers_attributes"=>{"0"=>{"contributor_id"=>"3", "_destroy"=>"", "id"=>"68"}, "1"=>{"contributor_id"=>"71", "_destroy"=>"", "id"=>"69"}, "2"=>{"contributor_id"=>"72", "_destroy"=>"", "id"=>"70"}, "3"=>{"contributor_id"=>"3", "_destroy"=>"", "id"=>"71"}}}, "commit"=>"Save", "id"=>"58"}
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = 2 LIMIT 1
Isbn Load (8.2ms) SELECT "isbns".* FROM "isbns" WHERE "isbns"."id" = 58 ORDER BY descriptivedetail_titledetail_titleelement_titlewithoutprefix LIMIT 1
Linker Load (0.3ms) SELECT "linkers".* FROM "linkers" WHERE "linkers"."id" IN (68, 69, 70, 71) AND ("linkers".isbn_id = 58)
AREL (0.4ms) UPDATE "linkers" SET "contributor_id" = 3, "updated_at" = '2011-06-09 11:34:14.509943' WHERE "linkers"."id" = 71
Contributor Load (158.3ms) SELECT "contributors".* FROM "contributors"
Redirected to http://localhost:3000/isbns/58
Completed 302 Found in 545ms
In other words, from an isbn edit form which has dynamically produced nested fields_for, using formtastic, I can use a drop down menu to select an existing contributor which has a many to many relationship with isbns.
Phew.
Related Topics
Execjs::Programerror in Welcome#Index Typeerror: Object Doesn't Support This Property or Method
Rake Db:Migrate Is Being Aborted Due to Rake Version Difference
Devise Install from Existing Model/Database
Accessing Variables from Included Files in Ruby
Generate a Nested JSON Array in Jbuilder
Using Ruby to Generate Sha512 Crypt-Style Hashes Formatted for /Etc/Shadow
Rails 3.2 Activeadmin 'Collection Is Not a Paginated Scope.' Error
Getting Ruby Function Object Itself
What's the Best Background Job Management Library for Rails
How to Render a String as an Erb File
Ruby: How to Write a Bang Method, Like Map
Ruby: Is Variable Is Object in Ruby
Rails: Detecting User Agent Works in Development But Not Production
Printing Elements of Array Using Erb
Need Help Maximizing 3 Factors in Multiple, Similar Objects and Ordering Appropriately
Ruby Tcpsocket: Find Out How Much Data Is Available
Installing Ruby Gem Less-Rails on Windows MAChine Using Therubyracer