ninja-model 0.4.2 → 0.5.1
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/.gitignore +19 -0
- data/Rakefile +0 -7
- data/autotest/discover.rb +1 -0
- data/lib/ninja_model.rb +22 -26
- data/lib/ninja_model/adapters.rb +33 -43
- data/lib/ninja_model/adapters/abstract_adapter.rb +2 -10
- data/lib/ninja_model/adapters/adapter_manager.rb +17 -10
- data/lib/ninja_model/adapters/adapter_pool.rb +15 -17
- data/lib/ninja_model/adapters/adapter_specification.rb +3 -3
- data/lib/ninja_model/associations.rb +25 -106
- data/lib/ninja_model/associations/association_proxy.rb +119 -1
- data/lib/ninja_model/associations/belongs_to_association.rb +5 -1
- data/lib/ninja_model/attribute.rb +130 -0
- data/lib/ninja_model/{attributes.rb → attribute_methods.rb} +21 -42
- data/lib/ninja_model/base.rb +23 -20
- data/lib/ninja_model/callbacks.rb +2 -11
- data/lib/ninja_model/identity.rb +6 -11
- data/lib/ninja_model/persistence.rb +15 -30
- data/lib/ninja_model/predicate.rb +4 -4
- data/lib/ninja_model/rails_ext/active_record.rb +187 -0
- data/lib/ninja_model/railtie.rb +14 -8
- data/lib/ninja_model/reflection.rb +7 -14
- data/lib/ninja_model/relation.rb +5 -3
- data/lib/ninja_model/relation/finder_methods.rb +4 -8
- data/lib/ninja_model/relation/spawn_methods.rb +1 -1
- data/lib/ninja_model/validation.rb +6 -23
- data/lib/ninja_model/version.rb +1 -1
- data/ninja-model.gemspec +28 -0
- data/spec/ninja_model/adapters/abstract_adapter_spec.rb +45 -0
- data/spec/ninja_model/adapters/adapter_manager_spec.rb +69 -0
- data/spec/ninja_model/adapters/adapter_pool_spec.rb +210 -48
- data/spec/ninja_model/adapters_spec.rb +77 -0
- data/spec/ninja_model/attribute_methods_spec.rb +95 -0
- data/spec/ninja_model/attribute_spec.rb +129 -0
- data/spec/ninja_model/base_spec.rb +4 -52
- data/spec/ninja_model/identity_spec.rb +16 -32
- data/spec/ninja_model/persistence_spec.rb +130 -4
- data/spec/ninja_model/predicate_spec.rb +40 -6
- data/spec/ninja_model/query_methods_spec.rb +76 -74
- data/spec/ninja_model/reflection_spec.rb +63 -0
- data/spec/ninja_model/relation_spec.rb +213 -20
- data/spec/ninja_model/symbol_spec.rb +19 -0
- data/spec/ninja_model/validation_spec.rb +18 -0
- data/spec/spec_helper.rb +9 -0
- data/spec/support/matchers/convert.rb +30 -0
- metadata +85 -63
- data/lib/ninja_model/associations/active_record_proxy.rb +0 -53
- data/lib/ninja_model/associations/ninja_model_proxy.rb +0 -46
- data/lib/ninja_model/configuration.rb +0 -20
- data/lib/ninja_model/errors.rb +0 -5
- data/lib/ninja_model/log_subscriber.rb +0 -18
- data/lib/ninja_model/scoping.rb +0 -50
- data/spec/ninja_model/attributes_spec.rb +0 -85
- data/spec/ninja_model/scoping_spec.rb +0 -40
data/lib/ninja_model/identity.rb
CHANGED
@@ -1,16 +1,11 @@
|
|
1
|
-
require 'active_support'
|
2
|
-
|
3
1
|
module NinjaModel
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
class_inheritable_accessor :primary_key
|
10
|
-
self.primary_key = :id
|
11
|
-
undef_method(:id) if method_defined?(:id)
|
12
|
-
end
|
2
|
+
class Base
|
3
|
+
class_inheritable_accessor :primary_key
|
4
|
+
self.primary_key = :id
|
5
|
+
undef_method(:id) if method_defined?(:id)
|
6
|
+
end
|
13
7
|
|
8
|
+
module Identity
|
14
9
|
def to_param
|
15
10
|
send(self.class.primary_key).to_s if persisted?
|
16
11
|
end
|
@@ -1,34 +1,15 @@
|
|
1
|
-
require 'active_support'
|
2
|
-
|
3
1
|
module NinjaModel
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
module ClassMethods
|
9
|
-
def get(rel)
|
10
|
-
end
|
11
|
-
|
12
|
-
def persist_with(adapter)
|
13
|
-
|
14
|
-
end
|
15
|
-
end
|
2
|
+
class Base
|
3
|
+
define_model_callbacks :save, :create, :update, :destroy
|
4
|
+
end
|
16
5
|
|
17
|
-
|
18
|
-
class_inheritable_accessor :persistence_adapter
|
19
|
-
end
|
6
|
+
module Persistence
|
20
7
|
|
21
8
|
def save(*)
|
22
9
|
run_callbacks :save do
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
def create_or_update
|
28
|
-
if new_record?
|
29
|
-
create
|
30
|
-
else
|
31
|
-
update
|
10
|
+
result = new_record? ? create : update
|
11
|
+
changed_attributes.clear if result
|
12
|
+
result
|
32
13
|
end
|
33
14
|
end
|
34
15
|
|
@@ -42,7 +23,9 @@ module NinjaModel
|
|
42
23
|
end
|
43
24
|
|
44
25
|
def update
|
45
|
-
|
26
|
+
run_callbacks :update do
|
27
|
+
self.class.adapter.update(self)
|
28
|
+
end
|
46
29
|
end
|
47
30
|
|
48
31
|
def new_record?
|
@@ -58,10 +41,12 @@ module NinjaModel
|
|
58
41
|
end
|
59
42
|
|
60
43
|
def destroy
|
61
|
-
|
62
|
-
|
44
|
+
run_callbacks :destroy do
|
45
|
+
if self.class.adapter.destroy(self)
|
46
|
+
@destroyed = true
|
47
|
+
end
|
48
|
+
@destroyed
|
63
49
|
end
|
64
|
-
@destroyed
|
65
50
|
end
|
66
51
|
|
67
52
|
def reload
|
@@ -3,11 +3,11 @@ module NinjaModel
|
|
3
3
|
|
4
4
|
PREDICATES = [:eq, :ne, :gt, :gte, :lt, :lte, :in]
|
5
5
|
|
6
|
-
attr_reader :attribute, :
|
6
|
+
attr_reader :attribute, :meth, :value
|
7
7
|
|
8
|
-
def initialize(attribute,
|
8
|
+
def initialize(attribute, meth, *args)
|
9
9
|
@attribute = attribute
|
10
|
-
@
|
10
|
+
@meth = meth
|
11
11
|
@valued = !args.blank?
|
12
12
|
@value = args.blank? ? nil : args.first
|
13
13
|
end
|
@@ -22,7 +22,7 @@ module NinjaModel
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def test(suspect)
|
25
|
-
case
|
25
|
+
case meth
|
26
26
|
when :eq
|
27
27
|
suspect.eql?(value)
|
28
28
|
when :ne
|
@@ -0,0 +1,187 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
class Base
|
5
|
+
class << self
|
6
|
+
def has_one_with_ninja_model(association_id, options = {})
|
7
|
+
if NinjaModel.ninja_model?(options[:class_name] || association_id)
|
8
|
+
ninja_proxy.handle_association(:has_one, association_id, options)
|
9
|
+
else
|
10
|
+
has_one_without_ninja_model(association_id, options)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
alias_method_chain :has_one, :ninja_model
|
14
|
+
|
15
|
+
def reflect_on_association_with_ninja_model(association)
|
16
|
+
if read_inheritable_attribute(:ninja_proxy) && ninja_proxy.proxy_klass.reflections.include?(association)
|
17
|
+
ninja_proxy.proxy_klass.reflect_on_association(association)
|
18
|
+
else
|
19
|
+
reflect_on_association_without_ninja_model(association)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
alias_method_chain :reflect_on_association, :ninja_model
|
24
|
+
|
25
|
+
def ninja_proxy
|
26
|
+
read_inheritable_attribute(:ninja_proxy) || write_inheritable_attribute(:ninja_proxy, NinjaModel::Associations::NinjaModelProxy.new(self))
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
def method_missing(method, *args)
|
32
|
+
begin
|
33
|
+
super
|
34
|
+
rescue NoMethodError => ex
|
35
|
+
if self.class.read_inheritable_attribute(:ninja_proxy) && ninja_proxy.respond_to?(method)
|
36
|
+
ninja_proxy.send(method, *args)
|
37
|
+
else
|
38
|
+
raise ex
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
module NinjaModel
|
46
|
+
|
47
|
+
class Base
|
48
|
+
class << self
|
49
|
+
def has_one_with_active_record(association_id, options = {})
|
50
|
+
if ninja_model?(:has_one, options[:class_name] || association_id)
|
51
|
+
has_one_without_active_record(association_id, options)
|
52
|
+
else
|
53
|
+
proxy.handle_association(:has_one, association_id, options)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
alias_method_chain :has_one, :active_record
|
58
|
+
|
59
|
+
def belongs_to_with_active_record(association_id, options = {})
|
60
|
+
if ninja_model?(:belongs_to, options[:class_name] || association_id)
|
61
|
+
belongs_to_without_active_record(association_id, options)
|
62
|
+
else
|
63
|
+
proxy.handle_association(:belongs_to, association_id, options)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
alias_method_chain :belongs_to, :active_record
|
68
|
+
|
69
|
+
def has_many_with_active_record(association_id, options = {})
|
70
|
+
if ninja_model?(:has_many, association_id)
|
71
|
+
has_many_without_active_record(association_id, options)
|
72
|
+
else
|
73
|
+
proxy.handle_association(:has_many, association_id, options)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
alias_method_chain :has_many, :active_record
|
78
|
+
|
79
|
+
def proxy
|
80
|
+
read_inheritable_attribute(:proxy) || write_inheritable_attribute(:proxy, Associations::ActiveRecordProxy.new(self))
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def method_missing(method, *args)
|
85
|
+
if self.class.read_inheritable_attribute(:proxy) && proxy.respond_to?(method)
|
86
|
+
proxy.send(method, *args)
|
87
|
+
else
|
88
|
+
super
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
module Associations
|
94
|
+
class ActiveRecordProxy
|
95
|
+
def initialize(ninja_model)
|
96
|
+
@klass = ninja_model
|
97
|
+
@klass.class_eval do
|
98
|
+
def proxy
|
99
|
+
@proxy ||= begin
|
100
|
+
self.class.proxy.instance(self)
|
101
|
+
end
|
102
|
+
@proxy.attributes = self.attributes.delete_if { |k,v| k.eql?('id') }
|
103
|
+
@proxy
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
@proxy_klass = ninja_model.parent.const_set("#{@klass.model_name}Proxy", Class.new(ActiveRecord::Base))
|
108
|
+
@proxy_klass.class_eval do
|
109
|
+
cattr_accessor :columns
|
110
|
+
self.columns = []
|
111
|
+
def self.column(name, sql_type = nil, default = nil)
|
112
|
+
self.columns << ActiveRecord::ConnectionAdapters::Column.new(name, nil, sql_type.to_s, default)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
@klass.model_attributes.each do |attr|
|
117
|
+
@proxy_klass.send :column, attr.name, attr.type, attr.default
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def instance(obj)
|
122
|
+
proxy = @proxy_klass.new
|
123
|
+
proxy.send :init_with, {'attributes' => obj.attributes}
|
124
|
+
proxy
|
125
|
+
end
|
126
|
+
|
127
|
+
def handle_association(macro, association_id, options)
|
128
|
+
unless macro.eql?(:belongs_to)
|
129
|
+
options = {:foreign_key => derive_foreign_key}.merge(options)
|
130
|
+
end
|
131
|
+
|
132
|
+
@proxy = nil
|
133
|
+
@proxy_klass.send macro, association_id, options
|
134
|
+
end
|
135
|
+
|
136
|
+
private
|
137
|
+
|
138
|
+
def derive_foreign_key
|
139
|
+
"#{@klass.name.underscore}_id".to_sym
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
class NinjaModelProxy
|
144
|
+
attr_reader :proxy_klass
|
145
|
+
def initialize(active_record)
|
146
|
+
@klass = active_record
|
147
|
+
@klass.class_eval do
|
148
|
+
def ninja_proxy
|
149
|
+
@ninja_proxy ||= begin
|
150
|
+
self.class.ninja_proxy.instance(self)
|
151
|
+
end
|
152
|
+
@ninja_proxy.attributes = self.attributes.delete_if { |k,v| k.eql?('id') }
|
153
|
+
@ninja_proxy
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
@proxy_klass = active_record.parent.const_set("#{@klass.model_name}Proxy", Class.new(NinjaModel::Base))
|
158
|
+
|
159
|
+
@klass.columns_hash.each_pair do |k,v|
|
160
|
+
@proxy_klass.send :attribute, k, v.type, v.default, @proxy_klass
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def instance(obj)
|
165
|
+
proxy = @proxy_klass.new
|
166
|
+
proxy.send :instantiate, {'attributes' => obj.attributes}
|
167
|
+
proxy
|
168
|
+
end
|
169
|
+
|
170
|
+
def handle_association(macro, association_id, options)
|
171
|
+
unless macro.eql?(:belongs_to)
|
172
|
+
options = {:foreign_key => derive_foreign_key}.merge(options)
|
173
|
+
end
|
174
|
+
|
175
|
+
@proxy = nil
|
176
|
+
@proxy_klass.send macro, association_id, options
|
177
|
+
end
|
178
|
+
|
179
|
+
private
|
180
|
+
|
181
|
+
def derive_foreign_key
|
182
|
+
"#{@klass.name.underscore}_id".to_sym
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
end
|
data/lib/ninja_model/railtie.rb
CHANGED
@@ -1,27 +1,33 @@
|
|
1
|
-
require 'ninja_model'
|
2
|
-
require 'rails/all'
|
3
|
-
|
4
1
|
module NinjaModel
|
5
2
|
class Railtie < Rails::Railtie
|
6
3
|
|
7
|
-
config.ninja_model =
|
4
|
+
config.ninja_model = ActiveSupport::OrderedOptions.new
|
8
5
|
|
9
|
-
|
6
|
+
config.app_middleware.insert_after "::ActionDispatch::Callbacks",
|
7
|
+
"NinjaModel::Adapters::AdapterManagement"
|
10
8
|
|
11
9
|
initializer 'ninja_model.logger' do |app|
|
12
10
|
NinjaModel::set_logger(Rails.logger)
|
13
11
|
end
|
14
12
|
|
15
|
-
|
16
|
-
|
13
|
+
initializer 'ninja_model_extend_active_record' do |app|
|
14
|
+
ActiveSupport.on_load(:active_record) do
|
15
|
+
require 'ninja_model/rails_ext/active_record'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
initializer 'ninja_model_load_specs' do |app|
|
20
|
+
config_path = File.join(app.paths.config.to_a.first, "ninja_model.yml")
|
17
21
|
if File.exists?(config_path)
|
18
22
|
require 'erb'
|
19
23
|
require 'yaml'
|
20
24
|
app.config.ninja_model.specs = YAML::load(ERB.new(IO.read(config_path)).result)
|
21
|
-
NinjaModel::Base.set_adapter
|
22
25
|
else
|
23
26
|
NinjaModel.logger.warn "[ninja-model] *WARNING* Unable to find configuration file at #{config_path}"
|
24
27
|
end
|
25
28
|
end
|
29
|
+
|
30
|
+
config.after_initialize do |app|
|
31
|
+
end
|
26
32
|
end
|
27
33
|
end
|
@@ -1,13 +1,10 @@
|
|
1
1
|
module NinjaModel
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
module ClassMethods
|
2
|
+
class Base
|
3
|
+
class << self
|
6
4
|
def create_reflection(macro, name, options, ninja_model)
|
7
5
|
case macro
|
8
6
|
when :has_many, :belongs_to, :has_one
|
9
|
-
reflection = AssociationReflection.new(macro, name, options, ninja_model)
|
10
|
-
when :composed_of
|
7
|
+
reflection = Reflection::AssociationReflection.new(macro, name, options, ninja_model)
|
11
8
|
end
|
12
9
|
write_inheritable_hash :reflections, name => reflection
|
13
10
|
reflection
|
@@ -25,9 +22,12 @@ module NinjaModel
|
|
25
22
|
end
|
26
23
|
|
27
24
|
def reflect_on_association(association)
|
28
|
-
reflections[association].is_a?(AssociationReflection) ? reflections[association] : nil
|
25
|
+
reflections[association].is_a?(Reflection::AssociationReflection) ? reflections[association] : nil
|
29
26
|
end
|
30
27
|
end
|
28
|
+
end
|
29
|
+
|
30
|
+
module Reflection
|
31
31
|
|
32
32
|
class MacroReflection
|
33
33
|
def initialize(macro, name, options, ninja_model)
|
@@ -77,13 +77,6 @@ module NinjaModel
|
|
77
77
|
@association_foreign_key ||= @options[:association_foreign_key] || class_name.foreign_key
|
78
78
|
end
|
79
79
|
|
80
|
-
def check_validity!
|
81
|
-
check_validity_of_inverse!
|
82
|
-
end
|
83
|
-
|
84
|
-
def check_validity_of_inverse!
|
85
|
-
end
|
86
|
-
|
87
80
|
def collection?
|
88
81
|
@collection
|
89
82
|
end
|
data/lib/ninja_model/relation.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
require '
|
1
|
+
require 'ninja_model/relation/query_methods'
|
2
|
+
require 'ninja_model/relation/finder_methods'
|
3
|
+
require 'ninja_model/relation/spawn_methods'
|
2
4
|
|
3
5
|
module NinjaModel
|
4
6
|
class Relation
|
@@ -58,13 +60,13 @@ module NinjaModel
|
|
58
60
|
size.zero?
|
59
61
|
end
|
60
62
|
|
61
|
-
protected
|
62
|
-
|
63
63
|
alias :inspect! :inspect
|
64
64
|
def inspect
|
65
65
|
to_a.inspect
|
66
66
|
end
|
67
67
|
|
68
|
+
protected
|
69
|
+
|
68
70
|
def method_missing(method, *args, &block)
|
69
71
|
if Array.method_defined?(method)
|
70
72
|
to_a.send(method, *args, &block)
|
@@ -1,18 +1,14 @@
|
|
1
1
|
module NinjaModel
|
2
|
+
class RecordNotFound < NinjaModelError; end
|
2
3
|
module FinderMethods
|
3
4
|
def first(*args)
|
4
5
|
if args.any?
|
6
|
+
apply_finder_options(args.first).limit(1).to_a.first
|
5
7
|
else
|
6
8
|
find_first
|
7
9
|
end
|
8
10
|
end
|
9
11
|
|
10
|
-
def last(*args)
|
11
|
-
if args.any?
|
12
|
-
else
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
12
|
def all(*args)
|
17
13
|
args.any? ? apply_finder_options(args.first).to_a : to_a
|
18
14
|
end
|
@@ -24,7 +20,7 @@ module NinjaModel
|
|
24
20
|
apply_finder_options(options).find(*args)
|
25
21
|
else
|
26
22
|
case args.first
|
27
|
-
when :first, :
|
23
|
+
when :first, :all
|
28
24
|
send(args.first)
|
29
25
|
else
|
30
26
|
find_with_ids(*args)
|
@@ -53,7 +49,7 @@ module NinjaModel
|
|
53
49
|
result = find_one(ids.first)
|
54
50
|
expects_array ? [result] : result
|
55
51
|
else
|
56
|
-
|
52
|
+
raise NotImplementedError, "Finding by multiple id's is not implemented"
|
57
53
|
end
|
58
54
|
end
|
59
55
|
|