I always has doubts on using has_and_belongs_to_many rather than has_many :through association. I have a model like this: class Company < ActiveRecord::Base has_many :categories has_many :legal_representatives has_many :tenders has_many :documents end I don''t see any way to use another model for these associations, do you think it''s better to use has_many :through anyway? -- 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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
On 7 November 2011 12:15, Mauro <mrsanna1-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> I always has doubts on using has_and_belongs_to_many rather than > has_many :through association. > I have a model like this: > > class Company < ActiveRecord::Base > has_many :categories > has_many :legal_representatives > has_many :tenders > has_many :documents > end > > I don''t see any way to use another model for these associations, do > you think it''s better to use has_many :through anyway?I don''t understand what you are asking, you do not appear to be using habtm or has many through. Perhaps you can clarify the question further Colin -- 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 7 November 2011 13:43, Colin Law <clanlaw-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org> wrote:> On 7 November 2011 12:15, Mauro <mrsanna1-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: >> I always has doubts on using has_and_belongs_to_many rather than >> has_many :through association. >> I have a model like this: >> >> class Company < ActiveRecord::Base >> has_many :categories >> has_many :legal_representatives >> has_many :tenders >> has_many :documents >> end >> >> I don''t see any way to use another model for these associations, do >> you think it''s better to use has_many :through anyway? > > I don''t understand what you are asking, you do not appear to be using > habtm or has many through. Perhaps you can clarify the question > furtherFor example: I have a Company with many legal_representatives and a LegaRepresentative that has many companies. In this case you use a has_and_belongs_to_many or has_many :through? What''s reasoning that leads me to select has_and_belongs_to_many rather than has_many :through? -- 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 Nov 7, 2011, at 1:26 PM, Mauro wrote:> On 7 November 2011 13:43, Colin Law <clanlaw-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org> wrote: >> On 7 November 2011 12:15, Mauro <mrsanna1-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: >>> I always has doubts on using has_and_belongs_to_many rather than >>> has_many :through association. >>> I have a model like this: >>> >>> class Company < ActiveRecord::Base >>> has_many :categories >>> has_many :legal_representatives >>> has_many :tenders >>> has_many :documents >>> end >>> >>> I don''t see any way to use another model for these associations, do >>> you think it''s better to use has_many :through anyway? >> >> I don''t understand what you are asking, you do not appear to be using >> habtm or has many through. Perhaps you can clarify the question >> further > > For example: I have a Company with many legal_representatives and a > LegaRepresentative that has many companies. > In this case you use a has_and_belongs_to_many or has_many :through? > What''s reasoning that leads me to select has_and_belongs_to_many > rather than has_many :through?You choose has_many :through when you need to "decorate" the junction between the two models. Let''s say that you needed to capture the date that a particular legal representative entered into an agreement with a company. You can''t capture that in the strict habtm relationship -- that''s just a "dumb" join table and can only store the fact that the relationship exists. Walter -- 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 Mon, Nov 7, 2011 at 13:26, Mauro <mrsanna1-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> For example: I have a Company with many legal_representatives and a > LegaRepresentative that has many companies. > In this case you use a has_and_belongs_to_many or has_many :through? > What''s reasoning that leads me to select has_and_belongs_to_many > rather than has_many :through?The usual reason for using has_many :through (hmt) is that you need to attach some information to that relationship. For instance, you may want to record exactly *when* a given Legal_representative started representing a given Company, how much they''re charging, etc. If you are absolutely sure you don''t, and *never will*, need to attach any info to the relationship, then has_and_belongs_to_many (habtm) will do fine. BUT: First, but I''ve heard some people complain about difficulty getting that working (I haven''t, and don''t know what they were doing wrong), and secondly, if you''re wrong, I''ve heard that it''s very difficult to retrofit an existing habtm setup to become hmt (haven''t tried to do that myself). So, aside from declaring one more class, there''s no reason not to use hmt from the start. -Dave -- LOOKING FOR WORK! What: Ruby (on/off Rails), Python, other modern languages. Where: Northern Virginia, Washington DC (near Orange Line), and remote work. See: davearonson.com (main) * codosaur.us (code) * dare2xl.com (excellence). Specialization is for insects. (Heinlein) - Have Pun, Will Babble! (Aronson) -- 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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
On 7 November 2011 19:32, Dave Aronson <googlegroups2dave-BRiZGj7G2yRXqviUI+FSNg@public.gmane.org> wrote:> So, aside from declaring one more class, there''s no reason not to use > hmt from the start.Ok, that''s good, if I need or not to attach information to the relationship I can always use has_many :through. Can you suggest a name for the :through model between Company and LegalRepresentative? -- 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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
On Mon, Nov 7, 2011 at 13:53, Mauro <mrsanna1-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> Can you suggest a name for the :through model between Company and > LegalRepresentative?Off the top of my head, maybe LegalRepresentation? Or since it''s so close to an existing class, maybe just Representation? (Unless the Company needs other forms of Representation.) -Dave -- LOOKING FOR WORK! What: Ruby (on/off Rails), Python, other modern languages. Where: Northern Virginia, Washington DC (near Orange Line), and remote work. See: davearonson.com (main) * codosaur.us (code) * dare2xl.com (excellence). Specialization is for insects. (Heinlein) - Have Pun, Will Babble! (Aronson) -- 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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
The 07/11/11, Dave Aronson wrote:> The usual reason for using has_many :through (hmt) is that you need to > attach some information to that relationship. For instance, you may > want to record exactly *when* a given Legal_representative started > representing a given Company, how much they''re charging, etc. If you > are absolutely sure you don''t, and *never will*, need to attach any > info to the relationship, then has_and_belongs_to_many (habtm) will do > fine. > > BUT: > > First, but I''ve heard some people complain about difficulty getting > that working (I haven''t, and don''t know what they were doing wrong), > and secondly, if you''re wrong, I''ve heard that it''s very difficult to > retrofit an existing habtm setup to become hmt (haven''t tried to do > that myself). > > So, aside from declaring one more class, there''s no reason not to use > hmt from the start.I''ve also tried hmt and I find it too much complicated in practice. My use case is not exactly the same and starts from the simplest relationship. Say you have customers doing orders for meals we''ll have to bill for. We start from models like this: +-----------------------+ |Customer | |has_one :location | |has_many :orders | |has_many :bills | +-----------------------+ +-----------------------+ |Location | |belongs_to :customer | +-----------------------+ +-----------------------+ |Order | |belongs_to :customer | +-----------------------+ +-----------------------+ |Bill | |belongs_to :customer | +-----------------------+ Everythings goes fine... until customer Bob changes of home. If you want to take new orders with the new location, you just need to update the Bob''s location which is _WRONG_ because all previous recorded bills will change of location too. The common answer in RoR is to give the location a new kind of relation depending of a duration. Doing so, you may change your models to +------------------------------------------------------+ |Customer | |has_many :location, :through => :customer_locations | | | |has_many :orders | |has_many :bills | +------------------------------------------------------+ +------------------------------------------------------+ |Location | |has_many :customers, :through => :customer_locations | +------------------------------------------------------+ +------------------------------------------------------+ |CustomerLocation | |belongs_to :customer | |belongs_to :location | +------------------------------------------------------+ where CustomerLocation has datetimes to define the relation validity. So you''ll have to define when a relation is valid for both the current and old relations depending on the datetimes. This led to a lot of complexity to handle all cases in the code. Also, it''s going to be even more complex if a customer may have diets, categories, etc that can change over time while you need to track correct history. This is why I decided to take a new approach. I''ve written a plugin (not public, I don''t even know if someone else would be interested). With the ContextFriendly plugin, I give the Customer and Location models a context. Given the original models, it is as simple as +--------------------------+ |Customer | |has_one :location | |acts_as_context_friendly | +--------------------------+ +--------------------------+ |Location | |belongs_to :customers | |acts_as_context_friendly | +--------------------------+ Using the script from this plugin I can automatically create the migrations and models in the contexts "order" and "bill". In this case, it will add the following models: +-----------------------------+ |BillCustomer | |has_one :bill_location | |acts_as_context_friendly | | | |has_many :bills | +-----------------------------+ +-----------------------------+ |OrderCustomer | |has_one :order_location | |acts_as_context_friendly | | | |has_many :orders | +-----------------------------+ +-----------------------------+ |BillsLocation | |belongs_to :bill_customer | |acts_as_context_friendly | +-----------------------------+ +-----------------------------+ |OrderLocation | |belongs_to :order_customer | |acts_as_context_friendly | +-----------------------------+ Though, I have to manually check the models, migrations and relations for the contexts (the script creating them is really simple). An abstract of this approach could be: +-----------------+ +-----------------+ | orders | | bills | +-----------------+ +-----------------+ | | | | v v +-----------------+ +-----------------+ +-----------------+ |Context: none | |Context: order | |Context: bill | +-----------------+ +-----------------+ +-----------------+ | Customer | | Customer | | Customer | | Location | | Location | | Location | +-----------------+ +-----------------+ +-----------------+ This is why I add the new models composed by the context name and the reference model name. Now, the original context (none) can be understood as the "configuration records" from which I will create new records in the "order" (or any other) context. The "none" context is also called "reference". To register a new order for Bob, we only need to save Bob in the "order" context: bob = Customer.where(''name like ?'', ''Bob'') bob_in_order = OrderCustomer.new bob_in_order <= bob # Change Bob instance of context bob_in_order.save or in a simpler form: bob = Customer.where(''name like ?'', ''Bob'') bob.save_as(:OrderCustomer) If Bob is already in the "order" context, nothing else is done at this stage: no new record is saved. Also, when we want to add Bob from the "order" context to "bill" we can do: order_customer = OrderCustomer.where(''name like ?'', ''Bob'').last bill_customer = BillCustomer.new bill_customer <= order_customer # Change context from "order" to "bill" bill_customer.save or simply OrderCustomer.where(''name like ?'', ''Bob'').last.save_as(:BillCustomer) I''ve implemented other usefull methods such as Model.foreach_model_in_all_contexts() Model.foreach_model_in_other_contexts() or model_instance.context() # Give informations like context and reference names. With this approach, I fall back to the simplest relationships for models with the drawback of a lot more models. I find it much convenient to deal with these models than with hmt in practice, though. -- Nicolas Sebrecht -- 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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.