suweller / mongoid-autoinc

⬆ Auto incrementing fields for Mongoid documents
MIT License
62 stars 44 forks source link

Inheriting classes that use the same counter? #18

Closed jmuheim closed 8 years ago

jmuheim commented 10 years ago

We have the following class structure:

They are all stored in the same collection. We want to have an incrementing counter that is shared between all those classes, but your implementation doesn't support this as you use the model_name as namespace:

    def increment!(field, options)
      scope_key = options[:scope] ? evaluate_scope(options[:scope]) : nil
      seed = options[:seed]
      write_attribute(
          field.to_sym, Mongoid::Autoinc::Incrementor.new(
          self.class.model_name, field, scope_key, seed).inc # Use collection_name here!
      )
    end

Would it be possible to use collection_name instead? Thanks.

matsimitsu commented 10 years ago

If we use the collection name, then the scenario breaks where a user has multiple models in the same collection and wants separate counts.

Maybe there should be a way to override the key manually. @suweller ?

suweller commented 10 years ago

Why wouldn't setting autoinc on the parent work?

jmuheim commented 10 years ago

Because it seems to derive the scope from the current class, which is not the parent class.

suweller commented 10 years ago

As a quick fix, it's possible to overwrite the model_name of both child classes to use return the parent classes model_name. I'll take a look this Friday to see if it makes sense to add an option to overwrite the key.

jmuheim commented 10 years ago

Thanks, but changes like these can lead to unpredictable outcomes quickly.

We have meanwhile implemented our own way incrementing what we need, so it's not important for us anymore. But still I guess it would be a nice to have feature for your gem. :+1:

suweller commented 10 years ago

I'd be happy to take a look at your solution at the very least it gives me a good starting point for creating the version broad enough to include in mongoid-autoinc :-)

On Wed, Jan 8, 2014 at 10:50 AM, Joshua Muheim notifications@github.comwrote:

Thanks, but changes like these can lead to unpredictable outcomes quickly.

We have meanwhile implemented our own way incrementing what we need, so it's not important for us anymore. But still I guess it would be a nice to have feature for your gem. [image: :+1:]

— Reply to this email directly or view it on GitHubhttps://github.com/suweller/mongoid-autoinc/issues/18#issuecomment-31817637 .

jmuheim commented 10 years ago

Our implementation is very basic and has another pattern that yours:

class NumberPool
  include Mongoid::Document
  include Mongoid::Multitenancy::Document

  tenant :client

  field :name,    type: String
  field :counter, type: Integer

  index name: 1

  validates :name, uniqueness: true

  def self.draw(name, seed = 0)
    find_or_create_by(name: name) { |pool| pool.counter ||= seed }.next
  end

  def next
    inc :counter, 1
  end
end
require 'spec_helper'

describe NumberPool do
  it { should validate_uniqueness_of :name }

  describe '.draw' do
    it 'creates a new pool if not existing' do
      expect {
        NumberPool.draw 'my pool'
      }.to change(NumberPool, :count).by 1
    end

    it 'uses an existing pool' do
      create :number_pool, name: 'my pool'

      expect {
        NumberPool.draw 'my pool'
      }.not_to change NumberPool, :count
    end

    it 'increments by 1' do
      number_pool = create :number_pool, name: 'my pool'

      expect {
        NumberPool.draw 'my pool'
      }.to change { number_pool.reload.counter }.from(1).to 2
    end

    it 'accepts an initial seed' do
      NumberPool.draw('my pool', 123)

      expect(NumberPool.find_by(name: 'my pool').counter).to eq 124
    end

    it 'ignores a seed for an existing pool' do
      NumberPool.draw('my pool')
      NumberPool.draw('my pool', 123)

      expect(NumberPool.find_by(name: 'my pool').counter).to eq 2
    end

    it 'is multi tenancy aware' do
      expect(NumberPool.draw 'my pool').to eq 1

      Mongoid::Multitenancy.with_tenant(create(:client)) do
        expect(NumberPool.draw 'my pool').to eq 1
      end

      expect(NumberPool.unscoped.count).to eq 2
    end
  end
end