I have a People table and a Tasks table. Some People are Managers, some are Workers. Each Task has a Manager and a Worker. How do I define the relationships? I tried a STI setup, where Managers and Workers inherit from People, and People has a type column. In my Task table, I have worker_id and manager_id rows. Then: task belongs_to worker task belongs_to manager worker has_many tasks manager has_many tasks But when I ask for task.worker, or task.manager, it throws an error. How can I do this without separate Worker and Manager tables? -- 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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
I think this could work: class Task < ActiveRecord::Base belongs_to :worker belongs_to :manager end class Person < ActiveRecord::Base end class Manager < Person has_many :tasks end class Worker < Person has_many :tasks end task = Task.create manager = Manager.create worker = Worker.create task.manager = manager task.worker = worker You don''t need to create two tables, only to files more... extending the model that is related to the table. Daniel Gaytán 2010/9/11 Brian Ablaza <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org>> I have a People table and a Tasks table. Some People are Managers, some > are Workers. Each Task has a Manager and a Worker. > > How do I define the relationships? I tried a STI setup, where Managers > and Workers inherit from People, and People has a type column. In my > Task table, I have worker_id and manager_id rows. Then: > > task belongs_to worker > task belongs_to manager > worker has_many tasks > manager has_many tasks > > But when I ask for task.worker, or task.manager, it throws an error. > > How can I do this without separate Worker and Manager tables? > -- > 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-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org<rubyonrails-talk%2Bunsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org> > . > 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.
I forgot to mention that you must to define a default scope for getting first all Managers or Workers in each case and a before create filter to set the role the person you are creating will have or whatever: #manager.rb before_create :set_manager_role default_scope :where => {:role => "manager"} private def set_manager_role self.role = "manager" end The same for the worker model 2010/9/11 Daniel Gaytán <daniel.gaytan.news-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>> I think this could work: > > class Task < ActiveRecord::Base > belongs_to :worker > belongs_to :manager > end > > class Person < ActiveRecord::Base > end > > class Manager < Person > has_many :tasks > end > > class Worker < Person > has_many :tasks > end > > task = Task.create > manager = Manager.create > worker = Worker.create > > task.manager = manager > task.worker = worker > > > You don''t need to create two tables, only to files more... extending the > model that is related to the table. > > Daniel Gaytán > > 2010/9/11 Brian Ablaza <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> > > I have a People table and a Tasks table. Some People are Managers, some >> are Workers. Each Task has a Manager and a Worker. >> >> How do I define the relationships? I tried a STI setup, where Managers >> and Workers inherit from People, and People has a type column. In my >> Task table, I have worker_id and manager_id rows. Then: >> >> task belongs_to worker >> task belongs_to manager >> worker has_many tasks >> manager has_many tasks >> >> But when I ask for task.worker, or task.manager, it throws an error. >> >> How can I do this without separate Worker and Manager tables? >> -- >> 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-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org<rubyonrails-talk%2Bunsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org> >> . >> 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.
script/generate migration add_roles_mask_to_users roles_mask:integer rake db:migrate # in models/user.rb ROLES = %w[Manager Worker] def roles=(roles) self.roles_mask = (roles & ROLES).map { |r| 2**ROLES.index(r) }.sum end def roles ROLES.reject do |r| ((roles_mask || 0) & 2**ROLES.index(r)).zero? end end def is?(role) roles.include?(role.to_s) end Or install the gem that does this http://rubygems.org/gems/role_model On Sat, Sep 11, 2010 at 11:07 PM, Daniel Gaytán < daniel.gaytan.news-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> I forgot to mention that you must to define a default scope for getting > first all Managers or Workers in each case and a before create filter to set > the role the person you are creating will have or whatever: > > #manager.rb > > before_create :set_manager_role > > default_scope :where => {:role => "manager"} > > private > > def set_manager_role > self.role = "manager" > end > > The same for the worker model > > > 2010/9/11 Daniel Gaytán <daniel.gaytan.news-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> > > I think this could work: >> >> class Task < ActiveRecord::Base >> belongs_to :worker >> belongs_to :manager >> end >> >> class Person < ActiveRecord::Base >> end >> >> class Manager < Person >> has_many :tasks >> end >> >> class Worker < Person >> has_many :tasks >> end >> >> task = Task.create >> manager = Manager.create >> worker = Worker.create >> >> task.manager = manager >> task.worker = worker >> >> >> You don''t need to create two tables, only to files more... extending the >> model that is related to the table. >> >> Daniel Gaytán >> >> 2010/9/11 Brian Ablaza <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> >> >> I have a People table and a Tasks table. Some People are Managers, some >>> are Workers. Each Task has a Manager and a Worker. >>> >>> How do I define the relationships? I tried a STI setup, where Managers >>> and Workers inherit from People, and People has a type column. In my >>> Task table, I have worker_id and manager_id rows. Then: >>> >>> task belongs_to worker >>> task belongs_to manager >>> worker has_many tasks >>> manager has_many tasks >>> >>> But when I ask for task.worker, or task.manager, it throws an error. >>> >>> How can I do this without separate Worker and Manager tables? >>> -- >>> 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-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org<rubyonrails-talk%2Bunsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org> >>> . >>> 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-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org<rubyonrails-talk%2Bunsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org> > . > 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.
i like this olution because roles can grow easily On Sat, Sep 11, 2010 at 11:29 PM, radhames brito <rbritom-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> script/generate migration add_roles_mask_to_users roles_mask:integer > rake db:migrate > > > # in models/user.rb > > ROLES = %w[Manager Worker] > > def roles=(roles) > self.roles_mask = (roles & ROLES).map { |r| 2**ROLES.index(r) }.sum > end > > def roles > ROLES.reject do |r| > > ((roles_mask || 0) & 2**ROLES.index(r)).zero? > > end > end > > > def is?(role) > roles.include?(role.to_s) > end > > > Or install the gem that does this http://rubygems.org/gems/role_model > > > > > > > On Sat, Sep 11, 2010 at 11:07 PM, Daniel Gaytán < > daniel.gaytan.news-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > >> I forgot to mention that you must to define a default scope for getting >> first all Managers or Workers in each case and a before create filter to set >> the role the person you are creating will have or whatever: >> >> #manager.rb >> >> before_create :set_manager_role >> >> default_scope :where => {:role => "manager"} >> >> private >> >> def set_manager_role >> self.role = "manager" >> end >> >> The same for the worker model >> >> >> 2010/9/11 Daniel Gaytán <daniel.gaytan.news-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> >> >> I think this could work: >>> >>> class Task < ActiveRecord::Base >>> belongs_to :worker >>> belongs_to :manager >>> end >>> >>> class Person < ActiveRecord::Base >>> end >>> >>> class Manager < Person >>> has_many :tasks >>> end >>> >>> class Worker < Person >>> has_many :tasks >>> end >>> >>> task = Task.create >>> manager = Manager.create >>> worker = Worker.create >>> >>> task.manager = manager >>> task.worker = worker >>> >>> >>> You don''t need to create two tables, only to files more... extending the >>> model that is related to the table. >>> >>> Daniel Gaytán >>> >>> 2010/9/11 Brian Ablaza <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> >>> >>> I have a People table and a Tasks table. Some People are Managers, some >>>> are Workers. Each Task has a Manager and a Worker. >>>> >>>> How do I define the relationships? I tried a STI setup, where Managers >>>> and Workers inherit from People, and People has a type column. In my >>>> Task table, I have worker_id and manager_id rows. Then: >>>> >>>> task belongs_to worker >>>> task belongs_to manager >>>> worker has_many tasks >>>> manager has_many tasks >>>> >>>> But when I ask for task.worker, or task.manager, it throws an error. >>>> >>>> How can I do this without separate Worker and Manager tables? >>>> -- >>>> 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-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org. >>>> To unsubscribe from this group, send email to >>>> rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org<rubyonrails-talk%2Bunsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org> >>>> . >>>> 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-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org<rubyonrails-talk%2Bunsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org> >> . >> 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.
Not exactly the same thing but I think you can relate. In an application I am working on right now I have 2 separate tables, one for Roles (manager, worker, etc) and another one for Users (people). I chose that design instead of keeping a list of roles in the code because it keeps my application ''cleaner'' in the sense that if a new role is needed a person with enough authority to do so can just add the new role to the DB through a maintenance page. The User record has a column for ''role_id'' that you can easily maintain also through the user pages. On Sep 11, 10:20 pm, Brian Ablaza <li...-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> wrote:> I have a People table and a Tasks table. Some People are Managers, some > are Workers. Each Task has a Manager and a Worker. > > How do I define the relationships? I tried a STI setup, where Managers > and Workers inherit from People, and People has a type column. In my > Task table, I have worker_id and manager_id rows. Then: > > task belongs_to worker > task belongs_to manager > worker has_many tasks > manager has_many tasks > > But when I ask for task.worker, or task.manager, it throws an error. > > How can I do this without separate Worker and Manager tables? > -- > Posted viahttp://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 12 September 2010 03:47, Daniel Gaytán <daniel.gaytan.news-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> I think this could work: > > class Task < ActiveRecord::Base > belongs_to :worker > belongs_to :manager > endThat will work as long as the OP doesn''t ever need a person to be a manager on one task, and a worker on another. Alternatively, create two foreign keys in Tasks and link them both to the Person model: class Task < ActiveRecord::Base belongs_to :worker, :foreign_key => "worker_id", :class_name => "Person" belongs_to :manager, :foreign_key => "manager_id", :class_name => "Person" end No STI is required, so there''s more flexibility for the Person model. -- 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 13 September 2010 09:46, Michael Pavling <pavling-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> Alternatively, create two foreign keys in Tasks and link them both to > the Person model: > > class Task < ActiveRecord::Base > belongs_to :worker, :foreign_key => "worker_id", :class_name => "Person" > belongs_to :manager, :foreign_key => "manager_id", :class_name => "Person" > endoh... and if you do have some criteria that determine who can be assigned to be a manager or worker, then then you can add a :conditions element too. So if you have a "people_permitted_to_manage" table, you can join to that to filter the person_id values that can go into manager_id in Task. HTH -- 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.
This works, as far as finding both workers and managers for any given task. All CRUD look good. I also need to sort on either the worker name or the manager name, or both. I can''t make this work, since there is no actual field named "worker.name", for example. My code looks like Task.find(:all, :order => "worker.name, manager.name") Since both workers and managers are actually in the Person table, I can''t see how this could work. Michael Pavling wrote:> On 12 September 2010 03:47, Daniel Gayt�n <daniel.gaytan.news@gmail.com> > wrote: >> I think this could work: >> >> class Task < ActiveRecord::Base >> belongs_to :worker >> belongs_to :manager >> end > > That will work as long as the OP doesn''t ever need a person to be a > manager on one task, and a worker on another. > > Alternatively, create two foreign keys in Tasks and link them both to > the Person model: > > class Task < ActiveRecord::Base > belongs_to :worker, :foreign_key => "worker_id", :class_name => > "Person" > belongs_to :manager, :foreign_key => "manager_id", :class_name => > "Person" > end > > No STI is required, so there''s more flexibility for the Person model.-- 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 14 September 2010 16:20, Brian Ablaza <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> wrote:> My code looks like > > Task.find(:all, :order => "worker.name, manager.name") > > Since both workers and managers are actually in the Person table, I > can''t see how this could work.Try : Task.find(:all, :include => [:worker, :manager], :order => "worker.name, manager.name") although that''s off the top of my head and I''m not able to look up the syntax of multiple includes right this second. HTH -- 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.
No luck. The query ends with "ORDER BY worker.name, manager.name", and as these are not columns in the Tasks table, it won''t work. Of course, it is possible to do this in SQL (i.e., sort tasks based on the names in the People table, with separate sorts for managers and workers). SELECT t.job_number, p1.name, p2.name FROM tasks AS t LEFT JOIN people AS p1 ON t.worker_id = p1.id LEFT JOIN people AS p2 ON t.manager_id = p2.id ORDER BY p1.name, p2.name Here, p1.name will be the worker name, and p2.name will be the manager name. The question is, should I struggle to generate this through ActiveRecord constructs, or just call the raw SQL? If there is a reasonable way to do this via AR, I''d rather do that, but I have no fear of the raw call. Michael Pavling wrote:> Try : > Task.find(:all, :include => [:worker, :manager], :order => > "worker.name, manager.name") > > although that''s off the top of my head and I''m not able to look up the > syntax of multiple includes right this second. > > HTH-- 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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
On 15 September 2010 22:36, Brian Ablaza <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> wrote:> No luck. The query ends with "ORDER BY worker.name, manager.name", and > as these are not columns in the Tasks table, it won''t work.Sorry, my quick answer was hideously wrong to assume the joins that AR would create would be called "worker" and "manager". I''ve just tried this on a table of mine, which has two associations to a "people" table, one as :person, and one as :owner, and the following works: Enrollment.all(:include => [:person, :owner], :order => "owners_enrollments.lastname, people.lastname") Please note that I discovered the table alias depends on the position in the array of includes (for instance if I had ":include => [:owner, :person]", the alias was different. But if you determine (I used the console to troubleshoot) what the alias is, then your query should work as you want as long as you don''t fiddle with it! -- 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.