Last active
February 22, 2019 14:10
-
-
Save 2called-chaos/46705324d913e4f9cc6b to your computer and use it in GitHub Desktop.
Usernamegen ActiveRecord example model and rake task
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# create_table "codenames", force: true do |t| | |
# t.integer "user_id" | |
# t.string "name" | |
# t.datetime "created_at" | |
# t.datetime "updated_at" | |
# end | |
# add_index "codenames", ["name"], name: "index_codenames_on_name", unique: true, using: :btree | |
# add_index "codenames", ["user_id"], name: "index_codenames_on_user_id", unique: true, using: :btree | |
class Codename < ActiveRecord::Base | |
class CodenameAllocRaceConditionError < Exception ; end | |
belongs_to :user, optional: true | |
scope :available, -> { where(user_id: nil) } | |
scope :allocated, -> { where.not(user_id: nil) } | |
validates :name, uniqueness: { case_sensitive: false } | |
def self.aquire(user) | |
# pessimistic locking to avoid race conditions | |
codename = nil | |
ActiveRecord::Base.uncached do | |
begin | |
codename = available.first | |
return nil unless codename | |
codename.with_lock do | |
if codename.user_id | |
raise CodenameAllocRaceConditionError | |
else | |
codename.update!(user: user) | |
end | |
end | |
codename | |
rescue CodenameAllocRaceConditionError | |
retry | |
end | |
end | |
user.id == codename.try(:user_id) ? codename : nil | |
end | |
def release! | |
update!(user_id: nil) | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace :codenames do | |
desc 'Import codenames from namegen pool' | |
task :import => :environment do | |
cwas = Codename.available.count | |
puts "#{cwas} in pool (before)" | |
Usernamegen.all.each do |name| | |
Codename.where(name: name).first_or_create! | |
end | |
cnow = Codename.available.count | |
puts "#{cnow} (+#{cnow-cwas}) in pool (after)" | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment