Richard Holland
Richard Holland

Reputation: 2683

Generate a scoped model id

Given

class Account < ActiveRecord::Base
  has_many :orders
end

I need to generate unique order numbers per account. Each account can have order 1000 BUT order 1000 can not exist in the same account.

@account1 = Account.first
@account1.orders.create(:price => 1.20) # order 1000 auto generated, next will be 1001

account1 then can not have two orders with a number 1000 but other accounts can.

I'm struggling with the best way to implement this.

Upvotes: 0

Views: 77

Answers (2)

Atastor
Atastor

Reputation: 741

I would add validation, e.g. add the following to your order model:

validates :order_no, :uniqueness => { :scope => :account, :message => "Try again saving, a deadlock might have occurred!"}

to make sure, the ids are actually unique and no deadlock occurred. Then add the following validation:

before_validation :generate_and_set_uniq_order_no

with

def generate_and_set_uniq_order_no
  # insert Amit's solution here, or anything else (e.g. sorting/unifying/incrementing)
end

to really GET a uniq id.

Upvotes: 1

Amit Patel
Amit Patel

Reputation: 15985

Use Table Sequencing where a table would hold last id for each account. The structure of your table would like

ACCOUNT_ID  CURRENT_ID
3283    1000
5078    1000
9000       1

Each time you create order increment, use it as order id and update CURRENT_ID for the account .

Note the issue with this solution is Concurrency and Deadlock

Upvotes: 1

Related Questions