Hello, I''m a web developer comping from Zend Framework and I''m trying to learn Rails the right way and avoid Bad Practice from the start. I have a few questions in my head that I''m unable to get answered on my own, so I''m going to try and get it explained with an example. Let''s say I''m building a site for a restaurant and the website have a Menu model (which is essentially categories, like Pizza, Burgers etc..), a Product model that belongs to the menu and an Ingredient model which belongs to Product, code: class Menu < ActiveRecord::Base has_many :products # … validations and other logic end class Product < ActiveRecord::Base belongs_to :menu has_many :ingredients accepts_nested_attributes_for :ingredients # … validations and other logic end class Ingredient < ActiveRecord::Base belongs_to :product validates :name, :presence => true, :unique => true # … other validations and other logic. end So far so good, however now I''m stuck because I''m not sure how to code what I have in mind without ending up with a spaghetti code. In the new product form, I would like the user to be able to add ingredients ( accepts_nested_attributes_for already there so I should be good for having the fields in the form ) but when the form has been filled and submitted, I want to create an ingredient if and only if it does not already exists, if on the other hand, it does, in this case the association should happen on the one that already exists, for example: Let''s say that I already have :onion in the ingredients table, if I added a new product that has onion, I should not have two rows for the :onion ingredient (should not happen since I added a validation), but instead the association should happen on the one that already exists.. How can I accomplish that? Should I be using a before_create hook? What should I do in that hook? or should I create a custom create method? Thank you. Wael -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
The easiest solution I could find to this problem is to remove accepts_nested_attributes_for from the Product model and in the controller do: @product = Product.new(params[:product]) @ingredient = find_or_initialise_by_name(params[:ingredient] if @product.save && @ingredient.save redirect_to @product, :flash => ''Success'' else redirect_to :new end What do you think guys, do you have a better solution ? Wael Nasreddine wrote in post #1000565:> Hello, > > I''m a web developer comping from Zend Framework and I''m trying to learn > Rails the right way and avoid Bad Practice from the start. > > I have a few questions in my head that I''m unable to get answered on my > own, so I''m going to try and get it explained with an example. > > Let''s say I''m building a site for a restaurant and the website have a > Menu model (which is essentially categories, like Pizza, Burgers etc..), > a Product model that belongs to the menu and an Ingredient model which > belongs to Product, code: > > class Menu < ActiveRecord::Base > has_many :products > > # … validations and other logic > end > > class Product < ActiveRecord::Base > belongs_to :menu > has_many :ingredients > > accepts_nested_attributes_for :ingredients > > # … validations and other logic > end > > class Ingredient < ActiveRecord::Base > belongs_to :product > > validates :name, :presence => true, :unique => true > > # … other validations and other logic. > end > > So far so good, however now I''m stuck because I''m not sure how to code > what I have in mind without ending up with a spaghetti code. In the new > product form, I would like the user to be able to add ingredients ( > accepts_nested_attributes_for already there so I should be good for > having the fields in the form ) but when the form has been filled and > submitted, I want to create an ingredient if and only if it does not > already exists, if on the other hand, it does, in this case the > association should happen on the one that already exists, for example: > > Let''s say that I already have :onion in the ingredients table, if I > added a new product that has onion, I should not have two rows for the > :onion ingredient (should not happen since I added a validation), but > instead the association should happen on the one that already exists.. > > How can I accomplish that? Should I be using a before_create hook? What > should I do in that hook? or should I create a custom create method? > > Thank you. > > Wael-- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
On May 24, 2011, at 6:06 AM, Wael Nasreddine wrote:> Hello, > > I''m a web developer comping from Zend Framework and I''m trying to > learn > Rails the right way and avoid Bad Practice from the start. > > I have a few questions in my head that I''m unable to get answered on > my > own, so I''m going to try and get it explained with an example. > > Let''s say I''m building a site for a restaurant and the website have a > Menu model (which is essentially categories, like Pizza, Burgers > etc..), > a Product model that belongs to the menu and an Ingredient model which > belongs to Product, code: > > class Menu < ActiveRecord::Base > has_many :products > > # … validations and other logic > end > > class Product < ActiveRecord::Base > belongs_to :menu > has_many :ingredients > > accepts_nested_attributes_for :ingredients > > # … validations and other logic > end > > class Ingredient < ActiveRecord::Base > belongs_to :product > > validates :name, :presence => true, :unique => true > > # … other validations and other logic. > end > > So far so good, however now I''m stuck because I''m not sure how to code > what I have in mind without ending up with a spaghetti code. In the > new > product form, I would like the user to be able to add ingredients ( > accepts_nested_attributes_for already there so I should be good for > having the fields in the form ) but when the form has been filled and > submitted, I want to create an ingredient if and only if it does not > already exists, if on the other hand, it does, in this case the > association should happen on the one that already exists, for example: > > Let''s say that I already have :onion in the ingredients table, if I > added a new product that has onion, I should not have two rows for the > :onion ingredient (should not happen since I added a validation), but > instead the association should happen on the one that already exists..This is a great place to look at find_or_create_by_[your attribute here]. I might try @ingredient = Ingredient.find_or_create_by_name params[:ingredient] [:name] @product.igredients << @ingredient Not sure about the params part, but the rest should work. Walter> > How can I accomplish that? Should I be using a before_create hook? > What > should I do in that hook? or should I create a custom create method? > > Thank you. > > Wael > > -- > Posted via http://www.ruby-forum.com/. > > -- > You received this message because you are subscribed to the Google > Groups "Ruby on Rails: Talk" group. > To post to this group, send email to rubyonrails- > talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org > To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com > . > For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en > . >-- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
On Tuesday, May 24, 2011 4:06:22 AM UTC-6, Ruby-Forum.com User wrote:> > Hello, > > I''m a web developer comping from Zend Framework and I''m trying to learn > Rails the right way and avoid Bad Practice from the start. > > I have a few questions in my head that I''m unable to get answered on my > own, so I''m going to try and get it explained with an example. > > Let''s say I''m building a site for a restaurant and the website have a > Menu model (which is essentially categories, like Pizza, Burgers etc..), > a Product model that belongs to the menu and an Ingredient model which > belongs to Product, code: > > class Menu < ActiveRecord::Base > has_many :products > > # … validations and other logic > end > > class Product < ActiveRecord::Base > belongs_to :menu > has_many :ingredients > > accepts_nested_attributes_for :ingredients > > # … validations and other logic > end > > class Ingredient < ActiveRecord::Base > belongs_to :product > > validates :name, :presence => true, :unique => true > > # … other validations and other logic. > end > > So far so good, however now I''m stuck because I''m not sure how to code > what I have in mind without ending up with a spaghetti code. In the new > product form, I would like the user to be able to add ingredients ( > accepts_nested_attributes_for already there so I should be good for > having the fields in the form ) but when the form has been filled and > submitted, I want to create an ingredient if and only if it does not > already exists, if on the other hand, it does, in this case the > association should happen on the one that already exists, for example: > > Let''s say that I already have :onion in the ingredients table, if I > added a new product that has onion, I should not have two rows for the > :onion ingredient (should not happen since I added a validation), but > instead the association should happen on the one that already exists.. >I just want to clarify something (possibly unrelated). So, are you saying that if I have product A which includes an onion ingredient record, and I create product B and attempt to add an onion ingredient record, that A''s onion should be located and made to refer to product B? I''m guessing this IS NOT the behavior you want (one product stealing another''s ingredients). However, on my first pass, that''s what it kind of sounded like. Do you instead mean that you only an ingredient (name) to be unique amongst the set of ingredients that all belong to the same product (so product C can''t have two separate onion ingredient records)? Or, are you truly trying to keep the ingredients unique across the board (one onion record in the whole table, regardless of how many products _want_ to have it)? If it is the latter case, I''d think you''d need some kind of has_and_belongs_to_many relationship between products and ingredients (either a simple habtm join table or a full join model with has_many :through => ... relationships). Anyhow, sorry if this is tangential to your actual question.> How can I accomplish that? Should I be using a before_create hook? What > should I do in that hook? or should I create a custom create method? > > Thank you. > > Wael > > -- > Posted via http://www.ruby-forum.com/. >-- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.