ninja-model 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +2 -0
- data/README.md +1 -0
- data/Rakefile +38 -0
- data/lib/generators/ninja_model/model/model_generator.rb +19 -0
- data/lib/generators/ninja_model/model/templates/model.rb +7 -0
- data/lib/generators/ninja_model/scaffold/scaffold_generator.rb +69 -0
- data/lib/generators/ninja_model.rb +12 -0
- data/lib/ninja-model.rb +1 -0
- data/lib/ninja_model/adapters/abstract_adapter.rb +63 -0
- data/lib/ninja_model/adapters/adapter_manager.rb +67 -0
- data/lib/ninja_model/adapters/adapter_pool.rb +128 -0
- data/lib/ninja_model/adapters/adapter_specification.rb +11 -0
- data/lib/ninja_model/adapters.rb +70 -0
- data/lib/ninja_model/associations/active_record_proxy.rb +53 -0
- data/lib/ninja_model/associations/association_proxy.rb +8 -0
- data/lib/ninja_model/associations/belongs_to_association.rb +31 -0
- data/lib/ninja_model/associations/has_many_association.rb +36 -0
- data/lib/ninja_model/associations/has_one_association.rb +19 -0
- data/lib/ninja_model/associations/ninja_model_proxy.rb +46 -0
- data/lib/ninja_model/associations.rb +198 -0
- data/lib/ninja_model/attributes.rb +134 -0
- data/lib/ninja_model/base.rb +106 -0
- data/lib/ninja_model/callbacks.rb +14 -0
- data/lib/ninja_model/configuration.rb +20 -0
- data/lib/ninja_model/core_ext/symbol.rb +7 -0
- data/lib/ninja_model/errors.rb +5 -0
- data/lib/ninja_model/identity.rb +24 -0
- data/lib/ninja_model/log_subscriber.rb +18 -0
- data/lib/ninja_model/persistence.rb +76 -0
- data/lib/ninja_model/predicate.rb +43 -0
- data/lib/ninja_model/railtie.rb +27 -0
- data/lib/ninja_model/reflection.rb +118 -0
- data/lib/ninja_model/relation/finder_methods.rb +74 -0
- data/lib/ninja_model/relation/query_methods.rb +62 -0
- data/lib/ninja_model/relation/spawn_methods.rb +59 -0
- data/lib/ninja_model/relation.rb +80 -0
- data/lib/ninja_model/scoping.rb +50 -0
- data/lib/ninja_model/validation.rb +38 -0
- data/lib/ninja_model/version.rb +3 -0
- data/lib/ninja_model.rb +38 -0
- data/spec/ninja_model/adapters/adapter_pool_spec.rb +72 -0
- data/spec/ninja_model/adapters_spec.rb +8 -0
- data/spec/ninja_model/attributes_spec.rb +85 -0
- data/spec/ninja_model/base_spec.rb +66 -0
- data/spec/ninja_model/identity_spec.rb +41 -0
- data/spec/ninja_model/persistence_spec.rb +9 -0
- data/spec/ninja_model/predicate_spec.rb +13 -0
- data/spec/ninja_model/query_methods_spec.rb +76 -0
- data/spec/ninja_model/relation_spec.rb +26 -0
- data/spec/ninja_model/scoping_spec.rb +40 -0
- data/spec/ninja_model_spec.rb +11 -0
- data/spec/spec_helper.rb +9 -0
- data/spec/support/active_model_lint.rb +17 -0
- metadata +214 -0
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'ninja_model'
|
2
|
+
require 'rails/all'
|
3
|
+
|
4
|
+
module NinjaModel
|
5
|
+
class Railtie < Rails::Railtie
|
6
|
+
|
7
|
+
config.ninja_model = NinjaModel::Configuration.create
|
8
|
+
|
9
|
+
#config.generators.orm :ninja_model, :migration => false
|
10
|
+
|
11
|
+
initializer 'ninja_model.logger' do |app|
|
12
|
+
NinjaModel::set_logger(Rails.logger)
|
13
|
+
end
|
14
|
+
|
15
|
+
config.after_initialize do |app|
|
16
|
+
config_path = File.join(Rails.root, app.config.ninja_model.config_file_path)
|
17
|
+
if File.exists?(config_path)
|
18
|
+
require 'erb'
|
19
|
+
require 'yaml'
|
20
|
+
app.config.ninja_model.specs = YAML::load(ERB.new(IO.read(config_path)).result)
|
21
|
+
NinjaModel::Base.set_adapter
|
22
|
+
else
|
23
|
+
NinjaModel.logger.warn "[ninja-model] *WARNING* Unable to find configuration file at #{config_path}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
module NinjaModel
|
2
|
+
module Reflection
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
module ClassMethods
|
6
|
+
def create_reflection(macro, name, options, ninja_model)
|
7
|
+
case macro
|
8
|
+
when :has_many, :belongs_to, :has_one
|
9
|
+
reflection = AssociationReflection.new(macro, name, options, ninja_model)
|
10
|
+
when :composed_of
|
11
|
+
end
|
12
|
+
write_inheritable_hash :reflections, name => reflection
|
13
|
+
reflection
|
14
|
+
end
|
15
|
+
|
16
|
+
def ninja_model?(macro, association)
|
17
|
+
klass = association.to_s.camelize
|
18
|
+
klass = klass.singularize unless [:has_one, :belongs_to].include?(macro)
|
19
|
+
klass = klass.constantize
|
20
|
+
defined?(klass) && klass.ancestors.include?(NinjaModel::Base)
|
21
|
+
end
|
22
|
+
|
23
|
+
def reflections
|
24
|
+
read_inheritable_attribute(:reflections) || write_inheritable_attribute(:reflections, {})
|
25
|
+
end
|
26
|
+
|
27
|
+
def reflect_on_association(association)
|
28
|
+
reflections[association].is_a?(AssociationReflection) ? reflections[association] : nil
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class MacroReflection
|
33
|
+
def initialize(macro, name, options, ninja_model)
|
34
|
+
@macro, @name, @options, @ninja_model = macro, name, options, ninja_model
|
35
|
+
end
|
36
|
+
|
37
|
+
attr_reader :ninja_model, :name, :macro, :options
|
38
|
+
|
39
|
+
def klass
|
40
|
+
@klass ||= class_name.constantize
|
41
|
+
end
|
42
|
+
|
43
|
+
def class_name
|
44
|
+
@class_name ||= options[:class_name] || derive_class_name
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def derive_class_name
|
50
|
+
name.to_s.camelize
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
class AssociationReflection < MacroReflection
|
55
|
+
def initialize(macro, name, options, ninja_model)
|
56
|
+
super
|
57
|
+
@collection = [:has_many].include?(macro)
|
58
|
+
end
|
59
|
+
|
60
|
+
def build_association(*options)
|
61
|
+
klass.new(*options)
|
62
|
+
end
|
63
|
+
|
64
|
+
def create_association(*options)
|
65
|
+
klass.create(*options)
|
66
|
+
end
|
67
|
+
|
68
|
+
def create_association!(*options)
|
69
|
+
klass.create!(*options)
|
70
|
+
end
|
71
|
+
|
72
|
+
def primary_key_name
|
73
|
+
@primary_key_name ||= options[:foreign_key] || derive_primary_key_name
|
74
|
+
end
|
75
|
+
|
76
|
+
def association_foreign_key
|
77
|
+
@association_foreign_key ||= @options[:association_foreign_key] || class_name.foreign_key
|
78
|
+
end
|
79
|
+
|
80
|
+
def check_validity!
|
81
|
+
check_validity_of_inverse!
|
82
|
+
end
|
83
|
+
|
84
|
+
def check_validity_of_inverse!
|
85
|
+
end
|
86
|
+
|
87
|
+
def collection?
|
88
|
+
@collection
|
89
|
+
end
|
90
|
+
|
91
|
+
def validate?
|
92
|
+
!options[:validate].nil? ? options[:validate] : (options[:autosave] == true || macro == :has_many)
|
93
|
+
end
|
94
|
+
|
95
|
+
private
|
96
|
+
|
97
|
+
def belongs_to?
|
98
|
+
macro == :belongs_to
|
99
|
+
end
|
100
|
+
|
101
|
+
def derive_class_name
|
102
|
+
class_name = name.to_s.camelize
|
103
|
+
class_name = class_name.singularize if collection?
|
104
|
+
class_name
|
105
|
+
end
|
106
|
+
|
107
|
+
def derive_primary_key_name
|
108
|
+
if belongs_to?
|
109
|
+
"#{name}_id"
|
110
|
+
elsif options[:as]
|
111
|
+
"#{options[:as]}_id"
|
112
|
+
else
|
113
|
+
ninja_model.name.foreign_key
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module NinjaModel
|
2
|
+
module FinderMethods
|
3
|
+
def first(*args)
|
4
|
+
if args.any?
|
5
|
+
else
|
6
|
+
find_first
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def last(*args)
|
11
|
+
if args.any?
|
12
|
+
else
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def all(*args)
|
17
|
+
args.any? ? apply_finder_options(args.first).to_a : to_a
|
18
|
+
end
|
19
|
+
|
20
|
+
def find(*args)
|
21
|
+
options = args.extract_options!
|
22
|
+
|
23
|
+
if options.present?
|
24
|
+
apply_finder_options(options).find(*args)
|
25
|
+
else
|
26
|
+
case args.first
|
27
|
+
when :first, :last, :all
|
28
|
+
send(args.first)
|
29
|
+
else
|
30
|
+
find_with_ids(*args)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def exists?(id)
|
36
|
+
where(primary_key.to_sym => id).limit(1)
|
37
|
+
relation.first ? true : false
|
38
|
+
end
|
39
|
+
|
40
|
+
protected
|
41
|
+
|
42
|
+
def find_with_ids(*ids)
|
43
|
+
expects_array = ids.first.kind_of?(Array)
|
44
|
+
|
45
|
+
return ids.first if expects_array && ids.first.empty?
|
46
|
+
|
47
|
+
ids = ids.flatten.compact.uniq
|
48
|
+
|
49
|
+
case ids.size
|
50
|
+
when 0
|
51
|
+
raise RecordNotFound, "Couldn't find #{@klass.name} without an ID"
|
52
|
+
when 1
|
53
|
+
result = find_one(ids.first)
|
54
|
+
expects_array ? [result] : result
|
55
|
+
else
|
56
|
+
find_some(ids)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def find_one(id)
|
61
|
+
id = id.id if NinjaModel::Base === id
|
62
|
+
|
63
|
+
where(primary_key.to_sym => id).first
|
64
|
+
end
|
65
|
+
|
66
|
+
def find_first
|
67
|
+
if loaded?
|
68
|
+
@records.first
|
69
|
+
else
|
70
|
+
@first ||= limit(1).to_a[0]
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
|
3
|
+
module NinjaModel
|
4
|
+
module QueryMethods
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
def order(*args)
|
8
|
+
relation = clone
|
9
|
+
relation.ordering += args.flatten unless args.blank?
|
10
|
+
relation
|
11
|
+
end
|
12
|
+
|
13
|
+
def where(opts, *rest)
|
14
|
+
relation = clone
|
15
|
+
relation.predicates += build_predicates(opts, rest)
|
16
|
+
relation
|
17
|
+
end
|
18
|
+
|
19
|
+
def limit(value)
|
20
|
+
relation = clone
|
21
|
+
relation.limit_value = value
|
22
|
+
relation
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def build_predicates(opts, other = [])
|
28
|
+
case opts
|
29
|
+
when String
|
30
|
+
raise ArgumentError,
|
31
|
+
"NinjaModel doesn't work with strings...yet. You'll need to use a predicate (see NinjaModel::Predicate::PREDICATES for a list)."
|
32
|
+
when Array
|
33
|
+
opts.collect do |o|
|
34
|
+
build_predicates(o)
|
35
|
+
end.flatten!
|
36
|
+
when Hash
|
37
|
+
opts.to_a.map do |o|
|
38
|
+
raise ArgumentError, "Not sure what to do with #{o}" unless o.length.eql?(2)
|
39
|
+
k = o[0]
|
40
|
+
v = o[1]
|
41
|
+
|
42
|
+
case k
|
43
|
+
when NinjaModel::Predicate
|
44
|
+
k.value = klass.model_attributes_hash[k.attribute].convert(v)
|
45
|
+
k
|
46
|
+
when Symbol, String
|
47
|
+
raise ArgumentError, "#{klass} doesn't have an attribute #{k}." unless klass.attribute_method?(k)
|
48
|
+
p = NinjaModel::Predicate.new(k.to_sym, :eq)
|
49
|
+
p.value = klass.model_attributes_hash[p.attribute].convert(v)
|
50
|
+
p
|
51
|
+
else
|
52
|
+
raise ArgumentError, "#{k} isn't a predicate or a symbol."
|
53
|
+
end
|
54
|
+
end
|
55
|
+
when NinjaModel::Predicate
|
56
|
+
[opts]
|
57
|
+
else
|
58
|
+
raise ArgumentError, "Unknown argument to #{self}.where: #{opts.inspect}"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
|
3
|
+
module NinjaModel
|
4
|
+
module SpawnMethods
|
5
|
+
|
6
|
+
def merge(r)
|
7
|
+
merged_relation = clone
|
8
|
+
return merged_relation unless r
|
9
|
+
return to_a & r if r.is_a?(Array)
|
10
|
+
|
11
|
+
order_value = r.ordering
|
12
|
+
if order_value.present?
|
13
|
+
merged_relation.ordering = merged_relation.ordering + order_value
|
14
|
+
end
|
15
|
+
|
16
|
+
merged_predicates = @predicates + r.predicates
|
17
|
+
|
18
|
+
unless @predicates.empty?
|
19
|
+
seen = []
|
20
|
+
merged_predicates = merged_predicates.reverse.reject { |w|
|
21
|
+
nuke = false
|
22
|
+
if w.respond_to?(:operator) && w.operator == :==
|
23
|
+
attribute = w.attribute
|
24
|
+
nuke = seen[attribute]
|
25
|
+
seen[attribute] = true
|
26
|
+
end
|
27
|
+
nuke
|
28
|
+
}.reverse
|
29
|
+
end
|
30
|
+
merged_relation.predicates = merged_predicates
|
31
|
+
|
32
|
+
Relation::SINGLE_VALUE_ATTRS.reject { |m| m == :lock }.each do |method|
|
33
|
+
value = r.send(:"#{method}_value")
|
34
|
+
merged_relation.send(:"#{method}_value=", value) unless value.nil?
|
35
|
+
end
|
36
|
+
|
37
|
+
merged_relation
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
VALID_FIND_OPTIONS = [:conditions, :limit, :offset, :order]
|
42
|
+
|
43
|
+
def apply_finder_options(options)
|
44
|
+
relation = clone
|
45
|
+
return relation unless options
|
46
|
+
|
47
|
+
options.assert_valid_keys(VALID_FIND_OPTIONS)
|
48
|
+
finders = options.dup
|
49
|
+
finders.delete_if { |key, value| value.nil? }
|
50
|
+
|
51
|
+
([:order, :limit, :offset] & finders.keys).each do |finder|
|
52
|
+
relation = relation.send(finder, finders[finder])
|
53
|
+
end
|
54
|
+
|
55
|
+
relation = relation.where(finders[:conditions]) if options.key?(:conditions)
|
56
|
+
relation
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'active_support/core_ext/object/blank'
|
2
|
+
|
3
|
+
module NinjaModel
|
4
|
+
class Relation
|
5
|
+
include QueryMethods, FinderMethods, SpawnMethods
|
6
|
+
|
7
|
+
delegate :length, :each, :map, :collect, :all?, :include?, :to => :to_a
|
8
|
+
|
9
|
+
attr_reader :klass, :loaded
|
10
|
+
|
11
|
+
attr_accessor :ordering, :predicates, :limit_value, :offset_value
|
12
|
+
|
13
|
+
alias :loaded? :loaded
|
14
|
+
|
15
|
+
SINGLE_VALUE_ATTRS = [:limit, :offset]
|
16
|
+
MULTI_VALUE_ATTRS = [:ordering, :predicates]
|
17
|
+
|
18
|
+
def initialize(klass)
|
19
|
+
@klass = klass
|
20
|
+
@loaded = false
|
21
|
+
|
22
|
+
SINGLE_VALUE_ATTRS.each do |v|
|
23
|
+
instance_variable_set("@#{v}_value".to_sym, nil)
|
24
|
+
end
|
25
|
+
|
26
|
+
MULTI_VALUE_ATTRS.each do |v|
|
27
|
+
instance_variable_set("@#{v}".to_sym, [])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_a
|
32
|
+
@records ||= begin
|
33
|
+
records = @klass.adapter.read(self)
|
34
|
+
@loaded = true
|
35
|
+
records
|
36
|
+
end
|
37
|
+
end
|
38
|
+
alias :to_ary :to_a
|
39
|
+
|
40
|
+
def scoping
|
41
|
+
@klass.scoped_methods << self
|
42
|
+
begin
|
43
|
+
yield
|
44
|
+
ensure
|
45
|
+
@klass.scoped_methods.pop
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def size
|
50
|
+
to_a.length
|
51
|
+
end
|
52
|
+
|
53
|
+
def blank?
|
54
|
+
empty?
|
55
|
+
end
|
56
|
+
|
57
|
+
def empty?
|
58
|
+
size.zero?
|
59
|
+
end
|
60
|
+
|
61
|
+
protected
|
62
|
+
|
63
|
+
alias :inspect! :inspect
|
64
|
+
def inspect
|
65
|
+
to_a.inspect
|
66
|
+
end
|
67
|
+
|
68
|
+
def method_missing(method, *args, &block)
|
69
|
+
if Array.method_defined?(method)
|
70
|
+
to_a.send(method, *args, &block)
|
71
|
+
elsif @klass.scopes[method]
|
72
|
+
merge(@klass.send(method, *args, &block))
|
73
|
+
elsif @klass.respond_to?(method)
|
74
|
+
scoping { @klass.send(method, *args, &block) }
|
75
|
+
else
|
76
|
+
super
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
require 'active_support/core_ext/array'
|
3
|
+
require 'active_support/core_ext/kernel/singleton_class'
|
4
|
+
|
5
|
+
module NinjaModel
|
6
|
+
module Scoping
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
def scoped(options = nil)
|
11
|
+
if options
|
12
|
+
scoped.apply_finder_options(options)
|
13
|
+
else
|
14
|
+
current_scoped_methods ? relation.merge(current_scoped_methods) : relation.clone
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def scopes
|
19
|
+
read_inheritable_attribute(:scopes) || write_inheritable_attribute(:scopes, {})
|
20
|
+
end
|
21
|
+
|
22
|
+
def scope(name, scope_options = {}, &block)
|
23
|
+
name = name.to_sym
|
24
|
+
valid_scope_name?(name)
|
25
|
+
extension = Module.new(&block) if block_given?
|
26
|
+
|
27
|
+
scopes[name] = lambda do |*args|
|
28
|
+
options = scope_options.is_a?(Proc) ? scope_options.call(*args) : scope_options
|
29
|
+
relation = if options.is_a?(Hash)
|
30
|
+
scoped.apply_finder_options(options)
|
31
|
+
elsif options
|
32
|
+
scoped.merge(options)
|
33
|
+
else
|
34
|
+
scoped
|
35
|
+
end
|
36
|
+
|
37
|
+
extension ? relation.extending(extension) : relation
|
38
|
+
end
|
39
|
+
|
40
|
+
singleton_class.send(:redefine_method, name, &scopes[name])
|
41
|
+
end
|
42
|
+
|
43
|
+
def valid_scope_name?(name)
|
44
|
+
if !scopes[name] && respond_to?(name, true)
|
45
|
+
logger.warn "Creating scope :#{name}. Overwriting existing method #{self.name}.#{name}."
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'active_model'
|
2
|
+
|
3
|
+
module NinjaModel
|
4
|
+
module Validation
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
include ActiveModel::Validations
|
7
|
+
|
8
|
+
def save(options={})
|
9
|
+
run_callbacks :validation do
|
10
|
+
perform_validations(options) ? super : false
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def valid?(context = nil)
|
15
|
+
context ||= (persisted? ? :update : :create)
|
16
|
+
output = super(context)
|
17
|
+
errors.empty? && output
|
18
|
+
end
|
19
|
+
|
20
|
+
protected
|
21
|
+
|
22
|
+
def perform_validations(options={})
|
23
|
+
perform_validation = case options
|
24
|
+
when Hash
|
25
|
+
options[:validate] != false
|
26
|
+
else
|
27
|
+
ActiveSupport::Deprecation.warn "save(#{options}) is deprecated, please give save(:validate => #{options}) instead", caller
|
28
|
+
options
|
29
|
+
end
|
30
|
+
|
31
|
+
if perform_validation
|
32
|
+
valid?(options.is_a?(Hash) ? options[:context] : nil)
|
33
|
+
else
|
34
|
+
true
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/ninja_model.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'active_support'
|
2
|
+
require 'active_support/core_ext/hash/indifferent_access'
|
3
|
+
|
4
|
+
module NinjaModel
|
5
|
+
extend ActiveSupport::Autoload
|
6
|
+
|
7
|
+
autoload :Base
|
8
|
+
autoload :Adapters
|
9
|
+
autoload :Associations
|
10
|
+
autoload :Attributes
|
11
|
+
autoload :Callbacks
|
12
|
+
autoload :Configuration
|
13
|
+
autoload :Identity
|
14
|
+
autoload :Persistence
|
15
|
+
autoload :Predicate
|
16
|
+
autoload :Reflection
|
17
|
+
autoload :Relation
|
18
|
+
autoload :Scoping
|
19
|
+
autoload :Validation
|
20
|
+
|
21
|
+
autoload_under 'relation' do
|
22
|
+
autoload :QueryMethods
|
23
|
+
autoload :FinderMethods
|
24
|
+
autoload :SpawnMethods
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
class << self
|
29
|
+
attr_accessor :logger
|
30
|
+
|
31
|
+
def set_logger(logger)
|
32
|
+
::NinjaModel.logger = logger
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
require 'ninja_model/railtie'
|
38
|
+
require 'ninja_model/errors'
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'ninja_model'
|
3
|
+
|
4
|
+
describe NinjaModel::Adapters::AdapterPool do
|
5
|
+
before(:each) do
|
6
|
+
@spec = mock('AdapterSpecification') do
|
7
|
+
stubs(:adapter_method).returns(:dummy_adapter)
|
8
|
+
stubs(:config)
|
9
|
+
end
|
10
|
+
|
11
|
+
@adapter = mock('AbstractAdapter') do
|
12
|
+
stubs(:verify!)
|
13
|
+
end
|
14
|
+
|
15
|
+
@pool = NinjaModel::Adapters::AdapterPool.new(@spec)
|
16
|
+
@thread = mock('thread') do
|
17
|
+
stubs('object_id').returns(123)
|
18
|
+
end
|
19
|
+
Thread.stubs(:current).returns(@thread)
|
20
|
+
NinjaModel::Base.stubs(:dummy_adapter).returns(@adapter)
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should properly respond to connected?' do
|
24
|
+
@pool.connected?.should be_false
|
25
|
+
@pool.instance
|
26
|
+
@pool.connected?.should be_true
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should initialize from an AdapterSpecification' do
|
30
|
+
spec = mock('AdapterSpecification')
|
31
|
+
NinjaModel::Adapters::AdapterPool.new(spec).spec.should eql(spec)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should return a valid instance_id' do
|
35
|
+
(@pool.send :current_instance_id).should eql(@thread.object_id)
|
36
|
+
end
|
37
|
+
|
38
|
+
describe 'when creating an instance' do
|
39
|
+
it 'should create a valid instance' do
|
40
|
+
(@pool.send :new_instance).should eql(@adapter)
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should store the instance' do
|
44
|
+
@pool.stubs(:new_instance).returns(@adapter)
|
45
|
+
@pool.instance
|
46
|
+
@pool.instances.should include(@adapter)
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should assign the instance to the current_thread' do
|
50
|
+
@pool.stubs(:new_instance).returns(@adapter)
|
51
|
+
@pool.instance
|
52
|
+
@pool.stubs(:checkout).returns("new_instance")
|
53
|
+
@pool.instance.should_not eql("new_instance")
|
54
|
+
@pool.instance.should eql(@adapter)
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'should reuse an unallocated instance' do
|
58
|
+
@pool.stubs(:current_instance_id).returns(123)
|
59
|
+
inst = @pool.instance
|
60
|
+
@pool.release_instance(123)
|
61
|
+
@pool.instance.should eql(inst)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'should properly allocate/deallocate instances' do
|
66
|
+
@pool.stubs(:current_instance_id).returns(123)
|
67
|
+
@pool.expects(:checkout).returns(@adapter)
|
68
|
+
@pool.expects(:checkin)
|
69
|
+
@pool.with_instance do |instance|
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|