Drop-Down-Menu for Many-To-Many Relation in Rails Using Nested Attributes

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



Leave a reply



Submit