so here is what I am trying to do: when the user is creating a special offer, he writes down how many coupons there should be. Each of these coupons is stored in the database with a unique code.
Example:
He wants to sell 100 coupons for "Dinner offer". When he creates the "Dinner offer" and types in, that he wants 100 coupons, these 100 coupons should be generated. How am I supposed to do this?
Thanks.
It's hard to tell which parts of this you're asking for help on. Are you not sure how to generate unique coupon codes, not sure how to model it, not sure how to create multiple records at a time? I'll try to give a general answer of what I'd do if I were building this, and maybe that will be helpful to you.
I'd create two models, Offer
and Coupon
:
rails g model offer title:string user:references
rails g model coupon offer:references code:uuid
I don't know if you're using mysql or postgresql. I think uuid will only work on postgresql. If you're using mysql I guess make the code column a string instead. Or better yet, switch to postgresql. ;)
class Offer < ActiveRecord::Base
belongs_to :user
has_many :coupons
end
class Coupon < ActiveRecord::Base
belongs_to :coupon
before_create -> { self.code = SecureRandom.uuid }
end
I would index the database on your code
column and make it unique, and disallow code
from being nil
. Might as well make both columns disallow nil
, I'm a big believer in doing that wherever possible in the database:
class CreateCoupons < ActiveRecord::Migration
def change
create_table :coupons do |t|
t.references :offer, index: true, null: false
t.uuid :code, null: false
end
add_index :coupons, :code, unique: true
end
end
Normally when you create a coupon you'd just do:
offer.coupons.create!
And it would generate the code for you in the before_create
hook. But since you want to create like 100 of them at once, the simple way would be:
100.times { offer.coupons.create! }
But that's going to be kind of inefficient. I don't know of a way to get Rails to do an efficient INSERT of many records, so we're going to do it manually:
objs = []
100.times do
objs.push "(#{offer.id}, '#{SecureRandom.uuid}', '#{Time.now}', '#{Time.now}')"
end
Coupon.connection.execute("INSERT INTO coupons (offer_id, code, created_at, updated_at) VALUES #{objs.join(", ")}")
If there's a more Railsy way of doing this, someone please let us know.