Rails: Design Pattern to Store Order of Relations
I开发者_高级运维 have four models: Customer, QueueRed, QueueBlue, QueueGreen.
The Queue models have a one to many relationship with customers
A customer must always be in a queue
A customer can only be in one queue at a time
A customer can change queues
We must be able to find out the customers current position in their respective queue
In an object model the queues would just have an array property containing customers, but ActiveRecord doesn't have arrays.
In a DB I would probably create some extra tables just to handle the order of the stories in the queue.
My question is what it the best way to model the relationship in ActiveRecord? Obviously there are many ways this could be done, but what is the best or the most in line with how ActiveRecord should be used?
Cheers,
Chris
I'd suggest to create only two models: Customer and Queue.
Queue table should consists of: customer_id
, queue_type_id
, position
.
You can create also QueueType model, but it is not necesary.
Customer model:
has_one :queue
Queue model:
belongs_to :customer
validates_uniqueness_of :customer_id
validates_uniqueness_of :position, :scope => :queue_type_id
named_scope :red, :conditions => {:queue_type_id => 0}
named_scope :green, :conditions => {:queue_type_id => 1}
named_scope :blue, :conditions => {:queue_type_id => 2}
I added named scopes to handle colours of queues.
A customer can only be in one queue at a time
First validation in queue model should forbid customer to be in more than one queue.
A customer can change queues
@customer = Customer.first
@customer.queue.queue_type_id = 1
@customer.save
Here you shoud be carfull with position
in queue, because it has to be unique in scope of queue_type_id
.
We must be able to find out the customers current position in their respective queue
customer.queue.position
In an object model the queues would just have an array property containing customers, but ActiveRecord doesn't have arrays.
@queue = Queue.red
It returns array of customers. I don't know what you meant by "ActiveRecord doesn't have arrays".
A customer must always be in a queue
Hm, just:
@customer = Customer.new
@customer.build_queue
?
Or you can add some before_save
or maybe better, simple validation:
validate :ensure_customer_is_in_queue
def ensure_customer_is_in_queue
errors.add_to_base "Customer should be in a queue!" unless self.queue
end
You should probably be looking at the acts_as_list plugin.
This is a commment/addition to the accepted answer above.
acts_as_list is not designed for anything beyond a prototype, and out of the box it does not handle concurrency or data integrity at all. At the very least, you must set your isolation level to serializable! Here's a short screen cast with more information, and some workarounds.
精彩评论