diff --git a/README.md b/README.md index 0edf29c..baaed2e 100644 --- a/README.md +++ b/README.md @@ -81,6 +81,30 @@ end # will produce => "2011HOUSE00001", "2011HOUSE00002"... ``` +It's possible to pass :scope_by option as a simple method, Proc.new or lambda + +Ex: +```ruby +# :manufacturer should be a Car's instance method(like an ActiveRecord column) +class Car < ActiveRecord::Base + protokoll :code, :scope_by => :manufacturer +end +# will scope Cars by manufacturers, for example "Ford", "Chevrolet" + +# :manufacturer and :year should be Car's instance methods(like ActiveRecord columns) +class Car < ActiveRecord::Base + protokoll :code, :scope_by => lambda { |o| "#{o.manufacturer}-#{o.year}" } +end +# will scope Cars by for example "Ford-2016" + +# :manufacturer and :year should be Car's instance methods(like ActiveRecord columns) +class Car < ActiveRecord::Base + protokoll :code, :scope_by => Proc.new{ "#{manufacturer}-#{model}" } +end +# will scope Cars by for example "Ford-Mustang", "Chevrolet-Camaro" +``` + + ## reserve_number! object.reserve_number! @@ -116,6 +140,10 @@ Run the generator rails g protokoll:migration +Optional: If scope_by will be used run next generator as well + + rails g protokoll:migration:scope_by + and migrate your database rake db:migrate diff --git a/lib/generators/protokoll/migration/scope_by_generator.rb b/lib/generators/protokoll/migration/scope_by_generator.rb new file mode 100644 index 0000000..679d4e3 --- /dev/null +++ b/lib/generators/protokoll/migration/scope_by_generator.rb @@ -0,0 +1,26 @@ +require 'rails/generators' + +module Protokoll + module Generators + module Migration + class ScopeByGenerator < ::Rails::Generators::Base + + include Rails::Generators::Migration + + desc "Generate protokoll's scope_by migration" + def create_migration_file + migration_name = "add_scope_by_to_custom_auto_increments.rb" + migration_template migration_name, File.join('db', 'migrate', migration_name) + end + + def self.source_root + @source_root ||= File.expand_path(File.join(File.dirname(__FILE__), 'templates')) + end + + def self.next_migration_number(path) + Time.now.utc.strftime("%Y%m%d%H%M%S") + end + end + end + end +end diff --git a/lib/generators/protokoll/migration/templates/add_scope_by_to_custom_auto_increments.rb b/lib/generators/protokoll/migration/templates/add_scope_by_to_custom_auto_increments.rb new file mode 100644 index 0000000..d927195 --- /dev/null +++ b/lib/generators/protokoll/migration/templates/add_scope_by_to_custom_auto_increments.rb @@ -0,0 +1,12 @@ +class AddScopeByToCustomAutoIncrements < ActiveRecord::Migration + def up + add_column :custom_auto_increments, :counter_model_scope, :string + add_index :custom_auto_increments, [:counter_model_name, :counter_model_scope], + :unique => true, :name => :counter_model_name_scope + end + + def down + remove_index :custom_auto_increments, name: :counter_model_name_scope + remove_column :custom_auto_increments, :counter_model_scope, :string + end +end diff --git a/lib/protokoll/counter.rb b/lib/protokoll/counter.rb index 27818f7..8c7f1d1 100644 --- a/lib/protokoll/counter.rb +++ b/lib/protokoll/counter.rb @@ -3,7 +3,7 @@ module Protokoll class Counter def self.next(object, options) - element = Models::CustomAutoIncrement.find_or_create_by(counter_model_name: object.class.to_s.underscore) + element = Models::CustomAutoIncrement.find_or_create_by(build_attrs(object, options)) element.counter = options[:start] if outdated?(element, options) || element.counter == 0 element.counter += 1 @@ -18,6 +18,17 @@ def self.next(object, options) private + def self.build_attrs(object, options) + attrs = {counter_model_name: object.class.to_s.underscore} + return attrs unless options[:scope_by] + + scope_by = options[:scope_by].respond_to?(:call) ? + object.instance_eval(&options[:scope_by]) : + object.send(options[:scope_by]) + + attrs.merge(counter_model_scope: scope_by) + end + def self.outdated?(record, options) Time.now.utc.strftime(update_event(options)).to_i > record.updated_at.strftime(update_event(options)).to_i end diff --git a/lib/protokoll/protokoll.rb b/lib/protokoll/protokoll.rb index b73dbdc..2369c69 100644 --- a/lib/protokoll/protokoll.rb +++ b/lib/protokoll/protokoll.rb @@ -14,7 +14,8 @@ def protokoll(column, _options = {}) options = { :pattern => "%Y%m#####", :number_symbol => "#", :column => column, - :start => 0 } + :start => 0, + :scope_by => nil } options.merge!(_options) raise ArgumentError.new("pattern can't be nil!") if options[:pattern].nil? diff --git a/test/dummy/db/migrate/20110923024431_create_protocols.rb b/test/dummy/db/migrate/20110923024431_create_protocols.rb index d864728..2cf5582 100644 --- a/test/dummy/db/migrate/20110923024431_create_protocols.rb +++ b/test/dummy/db/migrate/20110923024431_create_protocols.rb @@ -2,6 +2,8 @@ class CreateProtocols < ActiveRecord::Migration def change create_table :protocols do |t| t.string :number + t.string :context + t.string :context_2 t.timestamps end diff --git a/test/dummy/db/migrate/20120222164124_create_custom_auto_increments.rb b/test/dummy/db/migrate/20120222164124_create_custom_auto_increments.rb index 93fba87..b559411 100644 --- a/test/dummy/db/migrate/20120222164124_create_custom_auto_increments.rb +++ b/test/dummy/db/migrate/20120222164124_create_custom_auto_increments.rb @@ -1,7 +1,7 @@ class CreateCustomAutoIncrements < ActiveRecord::Migration def up create_table :custom_auto_increments, :force => true do |t| - t.string :counter_model_name + t.string :counter_model_name t.integer :counter, :default => 0 t.timestamps end diff --git a/test/dummy/db/migrate/20160310030821_add_scope_by_to_custom_auto_increments.rb b/test/dummy/db/migrate/20160310030821_add_scope_by_to_custom_auto_increments.rb new file mode 100644 index 0000000..d927195 --- /dev/null +++ b/test/dummy/db/migrate/20160310030821_add_scope_by_to_custom_auto_increments.rb @@ -0,0 +1,12 @@ +class AddScopeByToCustomAutoIncrements < ActiveRecord::Migration + def up + add_column :custom_auto_increments, :counter_model_scope, :string + add_index :custom_auto_increments, [:counter_model_name, :counter_model_scope], + :unique => true, :name => :counter_model_name_scope + end + + def down + remove_index :custom_auto_increments, name: :counter_model_name_scope + remove_column :custom_auto_increments, :counter_model_scope, :string + end +end diff --git a/test/dummy/db/schema.rb b/test/dummy/db/schema.rb index fe11cc8..c40daaa 100644 --- a/test/dummy/db/schema.rb +++ b/test/dummy/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20120222164124) do +ActiveRecord::Schema.define(version: 20160310030821) do create_table "calls", force: :cascade do |t| t.string "number" @@ -21,15 +21,19 @@ create_table "custom_auto_increments", force: :cascade do |t| t.string "counter_model_name" - t.integer "counter", default: 0 + t.integer "counter", default: 0 t.datetime "created_at" t.datetime "updated_at" + t.string "counter_model_scope" end + add_index "custom_auto_increments", ["counter_model_name", "counter_model_scope"], name: "counter_model_name_scope", unique: true add_index "custom_auto_increments", ["counter_model_name"], name: "index_custom_auto_increments_on_counter_model_name" create_table "protocols", force: :cascade do |t| t.string "number" + t.string "context" + t.string "context_2" t.datetime "created_at" t.datetime "updated_at" end diff --git a/test/protokoll_test.rb b/test/protokoll_test.rb index 5290d16..858674d 100644 --- a/test/protokoll_test.rb +++ b/test/protokoll_test.rb @@ -388,6 +388,53 @@ class Protocol < ActiveRecord::Base assert_equal "2011092601", protocol3.number end + test "counter should consider instance method scope given" do + class Protocol < ActiveRecord::Base + protokoll :number, :scope_by => :context + end + + protocol1 = Protocol.create! context: 'scenario_1' + protocol2 = Protocol.create! context: 'scenario_2' + protocol3 = Protocol.create! context: 'scenario_1' + + assert_equal "20110900001", protocol1.number + assert_equal "20110900001", protocol2.number + assert_equal "20110900002", protocol3.number + end + + test "counter should consider Proc scope given" do + class Protocol < ActiveRecord::Base + protokoll :number, :scope_by => Proc.new { "#{context}-#{context_2}" } + end + + protocol1 = Protocol.create! context: 'scenario_1', context_2: 'case1' + protocol2 = Protocol.create! context: 'scenario_2', context_2: 'case1' + protocol3 = Protocol.create! context: 'scenario_1', context_2: 'case1' + protocol4 = Protocol.create! context: 'scenario_1', context_2: 'case2' + + assert_equal "20110900001", protocol1.number + assert_equal "20110900001", protocol2.number + assert_equal "20110900002", protocol3.number + assert_equal "20110900001", protocol4.number + end + + test "counter should consider lambda scope given" do + class Protocol < ActiveRecord::Base + protokoll :number, :scope_by => lambda { |o| "#{o.context}-#{o.context_2}" } + end + + protocol1 = Protocol.create! context: 'scenario_1', context_2: 'case1' + protocol2 = Protocol.create! context: 'scenario_2', context_2: 'case1' + protocol3 = Protocol.create! context: 'scenario_1', context_2: 'case1' + protocol4 = Protocol.create! context: 'scenario_1', context_2: 'case2' + + assert_equal "20110900001", protocol1.number + assert_equal "20110900001", protocol2.number + assert_equal "20110900002", protocol3.number + assert_equal "20110900001", protocol4.number + end + + test "rejects empty patterns" do assert_raise ArgumentError do