/lib/document_number.rb
class DocumentNumber
TIME_TO_WAIT = 1
def initialize(document)
@sequence = "#{document}_number_seq"
end
def get(time_prefix_format = '%y%m%d', number_of_digits = 6)
prefix = Time.zone.now.strftime(time_prefix_format)
start_value = prefix + ('0' * number_of_digits)
next_value = get_uncached_sequence
if start_value.to_i > next_value.to_i
set_value(start_value)
sleep(TIME_TO_WAIT)
next_value = get_uncached_sequence
end
next_value
end
def get_uncached_sequence
ActiveRecord::Base.uncached do
get_sequence
end
end
def get_sequence
next_value
rescue ActiveRecord::StatementInvalid => e # the sequence is not created yet
create_sequence
next_value
end
class << self
def get_order_number
number = new(:order).get('%y%m%d', 5)
"B#{number}"
end
def get_sub_order_number
number = new(:sub_order).get
"M#{number}"
end
def get_bill_number
"T#{new(:bill).get}"
end
def get_special_approval_number
"S#{new(:special_approval).get}"
end
end
private
def create_sequence
ActiveRecord::Base.connection.execute("create sequence #{@sequence}")
end
def next_value
ActiveRecord::Base.connection.select_value("select nextval('#{@sequence}')")
end
def set_value(value)
ActiveRecord::Base.connection.execute("select setval('#{@sequence}', #{value})")
end
end
migration
def change
ActiveRecord::Base.connection.execute("create sequence crowdfunding_number_seq")
end
config/application
config.autoload_paths << Rails.root.join('lib')
rails console
DocumentNumber
=> DocumentNumber
说明已经可以用这个类
model/order.rb
before_create :save_order_number
#保存后生成认筹编码
def save_order_number
self.order_number = DocumentNumber.get_order_number
end