Skip to content

Commit

Permalink
Move creation of scopes to persistence adapaters
Browse files Browse the repository at this point in the history
- extend the classes with create_scope method
- avoid expensive "klass.ancestors.map" checks
- ORM-specific code is in one place
  • Loading branch information
csmuc committed Mar 4, 2016
1 parent 24b1ad9 commit a333156
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 44 deletions.
18 changes: 18 additions & 0 deletions lib/aasm/persistence/active_record_persistence.rb
Expand Up @@ -31,6 +31,7 @@ module ActiveRecordPersistence
def self.included(base)
base.send(:include, AASM::Persistence::Base)
base.send(:include, AASM::Persistence::ActiveRecordPersistence::InstanceMethods)
base.extend AASM::Persistence::ActiveRecordPersistence::ClassMethods

base.after_initialize do
aasm_ensure_initial_state
Expand All @@ -40,6 +41,23 @@ def self.included(base)
base.validate :aasm_validate_states
end

module ClassMethods
def aasm_create_scope(state_machine_name, scope_name)
conditions = {
table_name => { aasm(state_machine_name).attribute_name => scope_name.to_s }
}
if ActiveRecord::VERSION::MAJOR >= 3
class_eval do
scope scope_name, lambda { where(conditions) }
end
else
class_eval do
named_scope scope_name, :conditions => conditions
end
end
end
end

module InstanceMethods

# Writes <tt>state</tt> to the state column and persists it to the database
Expand Down
46 changes: 2 additions & 44 deletions lib/aasm/persistence/base.rb
Expand Up @@ -63,53 +63,11 @@ def state_with_scope(name, *args)
private

def create_scope?(name)
@state_machine.config.create_scopes && !@klass.respond_to?(name)
@state_machine.config.create_scopes && !@klass.respond_to?(name) && @klass.respond_to?(:aasm_create_scope)
end

def create_scope(name)
if ancestors_include?("ActiveRecord::Base")
create_for_active_record(name)
elsif ancestors_include?("Mongoid::Document")
create_for_mongoid(name)
elsif ancestors_include?("MongoMapper::Document")
create_for_mongomapper(name)
end
end

def ancestors_include?(class_name)
@klass.ancestors.map { |klass| klass.to_s }.include?(class_name)
end

def create_for_active_record(name)
conditions = {
@klass.table_name => { @klass.aasm(@name).attribute_name => name.to_s }
}
if ActiveRecord::VERSION::MAJOR >= 3
@klass.class_eval do
scope name, lambda { where(conditions) }
end
else
@klass.class_eval do
named_scope name, :conditions => conditions
end
end
end

def create_for_mongoid(name)
klass = @klass
state_machine_name = @name
scope_options = lambda {
klass.send(
:where,
{ klass.aasm(state_machine_name).attribute_name.to_sym => name.to_s }
)
}
@klass.send(:scope, name, scope_options)
end

def create_for_mongomapper(name)
conditions = { @klass.aasm(@name).attribute_name.to_sym => name.to_s }
@klass.scope(name, lambda { @klass.where(conditions) })
@klass.aasm_create_scope(@name, name)
end
end # Base

Expand Down
8 changes: 8 additions & 0 deletions lib/aasm/persistence/mongo_mapper_persistence.rb
Expand Up @@ -33,13 +33,21 @@ module MongoMapperPersistence
def self.included(base)
base.send(:include, AASM::Persistence::Base)
base.send(:include, AASM::Persistence::MongoMapperPersistence::InstanceMethods)
base.extend AASM::Persistence::MongoMapperPersistence::ClassMethods

base.before_create :aasm_ensure_initial_state

# ensure state is in the list of states
base.validate :aasm_validate_states
end

module ClassMethods
def aasm_create_scope(state_machine_name, scope_name)
conditions = { aasm(state_machine_name).attribute_name.to_sym => scope_name.to_s }
scope(scope_name, lambda { where(conditions) })
end
end

module InstanceMethods

# Writes <tt>state</tt> to the state column and persists it to the database
Expand Down
13 changes: 13 additions & 0 deletions lib/aasm/persistence/mongoid_persistence.rb
Expand Up @@ -33,10 +33,23 @@ module MongoidPersistence
def self.included(base)
base.send(:include, AASM::Persistence::Base)
base.send(:include, AASM::Persistence::MongoidPersistence::InstanceMethods)
base.extend AASM::Persistence::MongoidPersistence::ClassMethods

base.after_initialize :aasm_ensure_initial_state
end

module ClassMethods
def aasm_create_scope(state_machine_name, scope_name)
scope_options = lambda {
send(
:where,
{ aasm(state_machine_name).attribute_name.to_sym => scope_name.to_s }
)
}
send(:scope, scope_name, scope_options)
end
end

module InstanceMethods

# Writes <tt>state</tt> to the state column and persists it to the database
Expand Down

0 comments on commit a333156

Please sign in to comment.