ninja-model 0.4.2 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. data/.gitignore +19 -0
  2. data/Rakefile +0 -7
  3. data/autotest/discover.rb +1 -0
  4. data/lib/ninja_model.rb +22 -26
  5. data/lib/ninja_model/adapters.rb +33 -43
  6. data/lib/ninja_model/adapters/abstract_adapter.rb +2 -10
  7. data/lib/ninja_model/adapters/adapter_manager.rb +17 -10
  8. data/lib/ninja_model/adapters/adapter_pool.rb +15 -17
  9. data/lib/ninja_model/adapters/adapter_specification.rb +3 -3
  10. data/lib/ninja_model/associations.rb +25 -106
  11. data/lib/ninja_model/associations/association_proxy.rb +119 -1
  12. data/lib/ninja_model/associations/belongs_to_association.rb +5 -1
  13. data/lib/ninja_model/attribute.rb +130 -0
  14. data/lib/ninja_model/{attributes.rb → attribute_methods.rb} +21 -42
  15. data/lib/ninja_model/base.rb +23 -20
  16. data/lib/ninja_model/callbacks.rb +2 -11
  17. data/lib/ninja_model/identity.rb +6 -11
  18. data/lib/ninja_model/persistence.rb +15 -30
  19. data/lib/ninja_model/predicate.rb +4 -4
  20. data/lib/ninja_model/rails_ext/active_record.rb +187 -0
  21. data/lib/ninja_model/railtie.rb +14 -8
  22. data/lib/ninja_model/reflection.rb +7 -14
  23. data/lib/ninja_model/relation.rb +5 -3
  24. data/lib/ninja_model/relation/finder_methods.rb +4 -8
  25. data/lib/ninja_model/relation/spawn_methods.rb +1 -1
  26. data/lib/ninja_model/validation.rb +6 -23
  27. data/lib/ninja_model/version.rb +1 -1
  28. data/ninja-model.gemspec +28 -0
  29. data/spec/ninja_model/adapters/abstract_adapter_spec.rb +45 -0
  30. data/spec/ninja_model/adapters/adapter_manager_spec.rb +69 -0
  31. data/spec/ninja_model/adapters/adapter_pool_spec.rb +210 -48
  32. data/spec/ninja_model/adapters_spec.rb +77 -0
  33. data/spec/ninja_model/attribute_methods_spec.rb +95 -0
  34. data/spec/ninja_model/attribute_spec.rb +129 -0
  35. data/spec/ninja_model/base_spec.rb +4 -52
  36. data/spec/ninja_model/identity_spec.rb +16 -32
  37. data/spec/ninja_model/persistence_spec.rb +130 -4
  38. data/spec/ninja_model/predicate_spec.rb +40 -6
  39. data/spec/ninja_model/query_methods_spec.rb +76 -74
  40. data/spec/ninja_model/reflection_spec.rb +63 -0
  41. data/spec/ninja_model/relation_spec.rb +213 -20
  42. data/spec/ninja_model/symbol_spec.rb +19 -0
  43. data/spec/ninja_model/validation_spec.rb +18 -0
  44. data/spec/spec_helper.rb +9 -0
  45. data/spec/support/matchers/convert.rb +30 -0
  46. metadata +85 -63
  47. data/lib/ninja_model/associations/active_record_proxy.rb +0 -53
  48. data/lib/ninja_model/associations/ninja_model_proxy.rb +0 -46
  49. data/lib/ninja_model/configuration.rb +0 -20
  50. data/lib/ninja_model/errors.rb +0 -5
  51. data/lib/ninja_model/log_subscriber.rb +0 -18
  52. data/lib/ninja_model/scoping.rb +0 -50
  53. data/spec/ninja_model/attributes_spec.rb +0 -85
  54. data/spec/ninja_model/scoping_spec.rb +0 -40
@@ -0,0 +1,19 @@
1
+ *~
2
+ *.cache
3
+ *.log
4
+ *.pid
5
+ tmp/**/*
6
+ doc/*
7
+ .DS_Store
8
+ db/*.sqlite3
9
+ doc/api
10
+ doc/app
11
+ doc/plugins
12
+ doc/*.dot
13
+ coverage/*
14
+ *.sw?
15
+ vendor/plugins/ns_web
16
+ Gemfile.lock
17
+ .bundle
18
+ *.gem
19
+ .rspec
data/Rakefile CHANGED
@@ -1,12 +1,9 @@
1
1
  require 'bundler'
2
- Bundler.setup
3
2
  Bundler::GemHelper.install_tasks
4
3
 
5
4
  require 'rake'
6
5
  require 'rake/rdoctask'
7
6
  require 'rspec/core/rake_task'
8
- require 'cucumber'
9
- require 'cucumber/rake/task'
10
7
 
11
8
  RSpec::Core::RakeTask.new(:spec) do |t|
12
9
  t.verbose = false
@@ -32,7 +29,3 @@ namespace :spec do
32
29
  t.rcov_opts << %w{--exclude gems\/,spec\/}
33
30
  end
34
31
  end
35
-
36
- Cucumber::Rake::Task.new(:features) do |t|
37
- t.cucumber_opts = "features --format progress"
38
- end
@@ -0,0 +1 @@
1
+ Autotest.add_discovery { 'rspec2' }
@@ -1,29 +1,8 @@
1
- require 'active_support'
2
- require 'active_support/core_ext/hash/indifferent_access'
1
+ require 'active_model'
2
+ require 'active_support/core_ext'
3
3
 
4
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
-
5
+ class NinjaModelError < StandardError; end
27
6
 
28
7
  class << self
29
8
  attr_accessor :logger
@@ -31,8 +10,25 @@ module NinjaModel
31
10
  def set_logger(logger)
32
11
  ::NinjaModel.logger = logger
33
12
  end
13
+
14
+ def ninja_model?(symbol)
15
+ klass = symbol.to_s.camelize
16
+ klass = klass.singularize
17
+ klass = klass.constantize
18
+ klass.ancestors.include?(NinjaModel::Base)
19
+ end
20
+
21
+ def configuration
22
+ Rails.application.config.ninja_model
23
+ end
24
+ end
25
+
26
+ class Base
34
27
  end
35
28
  end
36
29
 
37
- require 'ninja_model/railtie'
38
- require 'ninja_model/errors'
30
+ require 'ninja_model/base'
31
+ require 'ninja_model/core_ext/symbol'
32
+ if defined?(Rails)
33
+ require 'ninja_model/railtie'
34
+ end
@@ -1,18 +1,14 @@
1
- require 'active_support'
1
+ require 'ninja_model/adapters/abstract_adapter'
2
+ require 'ninja_model/adapters/adapter_manager'
3
+ require 'ninja_model/adapters/adapter_pool'
4
+ require 'ninja_model/adapters/adapter_specification'
2
5
 
3
6
  module NinjaModel
4
7
 
5
8
  module Adapters
6
- extend ActiveSupport::Concern
7
- extend ActiveSupport::Autoload
8
-
9
- autoload :AdapterSpecification
10
- autoload :AdapterManager
11
- autoload :AdapterPool
12
- autoload :AbstractAdapter
13
-
14
- class << self
15
- end
9
+ class AdapterNotSpecified < StandardError; end
10
+ class InvalidAdapter < StandardError; end
11
+ class InvalidSpecification < StandardError; end
16
12
  end
17
13
 
18
14
  class Base
@@ -20,47 +16,41 @@ module NinjaModel
20
16
  self.adapter_manager = NinjaModel::Adapters::AdapterManager.new
21
17
 
22
18
  def adapter
23
- self.class.adapter
19
+ self.class.retrieve_adapter
24
20
  end
25
21
 
26
- def self.set_adapter(spec = nil)
27
- case spec
28
- when nil
29
- raise AdapterNotSpecified unless defined?(Rails.env)
30
- set_adapter(Rails.env)
31
- when AdapterSpecification
32
- self.adapter_manager.create_adapter(name, spec)
33
- when Symbol, String
34
- if config = NinjaModel.configuration.specs[spec.to_s]
35
- set_adapter(config)
36
- else
37
- raise AdapterNotSpecified, "#{spec} is not configured"
38
- end
39
- else
40
- spec = spec.symbolize_keys
41
- unless spec.key?(:adapter) then raise AdapterNotSpecified, "configuration does not specify adapter" end
42
- begin
43
- require File.join(NinjaModel.configuration.adapter_path, "#{spec[:adapter]}_adapter")
44
- rescue LoadError => e
45
- raise "Please install (or create) the #{spec[:adapter]} adapter. Search path is #{NinjaModel.configuration.adapter_path}"
46
- end
47
- adapter_method = "#{spec[:adapter]}_adapter"
48
- if !respond_to?(adapter_method)
49
- raise AdapterNotFound, "ninja configuration specifies nonexistent #{spec[:adapter]} adapter"
50
- end
51
- shutdown_adapter
52
- set_adapter(AdapterSpecification.new(spec, adapter_method))
22
+ class << self
23
+ def register_adapter(name, klass)
24
+ Adapters::AdapterManager.register_adapter_class(name, klass)
53
25
  end
54
- end
55
26
 
56
- class << self
57
- def adapter
58
- retrieve_adapter
27
+ def set_adapter(spec = nil)
28
+ case spec
29
+ when nil
30
+ raise Adapters::AdapterNotSpecified unless defined?(Rails.env)
31
+ set_adapter(Rails.env)
32
+ when Adapters::AdapterSpecification
33
+ self.adapter_manager.create_adapter(name, spec)
34
+ when Symbol, String
35
+ if config = NinjaModel.configuration.specs[spec.to_s]
36
+ set_adapter(config)
37
+ else
38
+ raise Adapters::InvalidSpecification, "#{spec} is not configured"
39
+ end
40
+ else
41
+ spec = spec.symbolize_keys
42
+ raise Adapters::AdapterNotSpecified, "configuration does not specify adapter" unless spec.key?(:adapter)
43
+ adapter_name = spec[:adapter]
44
+ raise Adapters::InvalidAdapter, "configuration does not specify adapter" unless Adapters::AdapterManager.registered?(adapter_name)
45
+ shutdown_adapter
46
+ set_adapter(Adapters::AdapterSpecification.new(spec, adapter_name))
47
+ end
59
48
  end
60
49
 
61
50
  def retrieve_adapter
62
51
  adapter_manager.retrieve_adapter(self)
63
52
  end
53
+ alias :adapter :retrieve_adapter
64
54
 
65
55
  def shutdown_adapter(klass = self)
66
56
  adapter_manager.remove_adapter(klass)
@@ -1,14 +1,10 @@
1
1
  module NinjaModel
2
2
  module Adapters
3
3
  class AbstractAdapter
4
- class << self
5
- def instance
6
- @instance ||= new
7
- end
8
- end
4
+ attr_reader :config
9
5
 
10
6
  def initialize(config, logger = nil)
11
- @active = nil
7
+ @active = false
12
8
  @config, @logger = config, logger
13
9
  end
14
10
 
@@ -54,10 +50,6 @@ module NinjaModel
54
50
  def destroy(model)
55
51
  false
56
52
  end
57
-
58
- def raw_connection
59
- @connection
60
- end
61
53
  end
62
54
  end
63
55
  end
@@ -1,10 +1,23 @@
1
1
  module NinjaModel
2
2
  module Adapters
3
3
  class AdapterManager
4
+ class_attribute :registered
5
+ self.registered = {}
6
+ class << self
7
+ def registered?(name)
8
+ registered.key?(name.to_sym)
9
+ end
10
+
11
+ def register_adapter_class(name, klass)
12
+ registered[name.to_sym] = klass
13
+ end
14
+ end
15
+
4
16
  attr_reader :adapter_pools
5
17
 
6
18
  def initialize(pools = {})
7
19
  @adapter_pools = pools
20
+ @registered = {}
8
21
  end
9
22
 
10
23
  def create_adapter(name, spec)
@@ -13,13 +26,7 @@ module NinjaModel
13
26
 
14
27
  def release_active_adapters!
15
28
  @adapter_pools.each_value do |pool|
16
- pool.release_adapter
17
- end
18
- end
19
-
20
- def release_reloadable_adapters!
21
- @adapter_pools.each_value do |pool|
22
- pool.shutdown_reloadable_adapters!
29
+ pool.release_instance
23
30
  end
24
31
  end
25
32
 
@@ -31,7 +38,7 @@ module NinjaModel
31
38
 
32
39
  def retrieve_adapter(klass)
33
40
  pool = retrieve_adapter_pool(klass)
34
- (pool && pool.instance) or raise StandardError
41
+ (pool && pool.instance) or raise StandardError, "Pool is empty or instance is null"
35
42
  end
36
43
 
37
44
  def remove_adapter(klass)
@@ -58,8 +65,8 @@ module NinjaModel
58
65
  def call(env)
59
66
  @app.call(env)
60
67
  ensure
61
- unless env.key?('rake.test')
62
- NinjaModel::Base.clear_active_instances!
68
+ unless env.key?('rack.test')
69
+ NinjaModel::Base.adapter_manager.release_active_adapters!
63
70
  end
64
71
  end
65
72
  end
@@ -1,4 +1,5 @@
1
1
  module NinjaModel
2
+ class ConnectionTimeoutError < NinjaModelError; end
2
3
  module Adapters
3
4
  class AdapterPool
4
5
  attr_reader :spec, :instances
@@ -13,6 +14,10 @@ module NinjaModel
13
14
  @timeout = 3
14
15
  end
15
16
 
17
+ def connected?
18
+ !@instances.empty?
19
+ end
20
+
16
21
  def instance
17
22
  NinjaModel.logger.debug("instance called for #{current_instance_id}")
18
23
  @assigned_instances[current_instance_id] ||= checkout
@@ -31,8 +36,15 @@ module NinjaModel
31
36
  release_instance(instance_id) if fresh_instance
32
37
  end
33
38
 
34
- def connected?
35
- !@instances.empty?
39
+ def shutdown!
40
+ @assigned_instances.each do |name,conn|
41
+ checkin conn
42
+ end
43
+ @assigned_instances = {}
44
+ @instances.each do |inst|
45
+ inst.disconnect!
46
+ end
47
+ @instances = []
36
48
  end
37
49
 
38
50
  private
@@ -86,7 +98,7 @@ module NinjaModel
86
98
  end
87
99
 
88
100
  def new_instance
89
- NinjaModel::Base.send(spec.adapter_method, spec.config)
101
+ AdapterManager.registered[spec.name.to_sym].new(spec.config)
90
102
  end
91
103
 
92
104
  def current_instance_id
@@ -110,19 +122,5 @@ module NinjaModel
110
122
  inst
111
123
  end
112
124
  end
113
-
114
- class AdapterManagement
115
- def initialize(app)
116
- @app = app
117
- end
118
-
119
- def call(env)
120
- @app.call(env)
121
- ensure
122
- unless env.key?('rask.test')
123
- NinjaModel::Base.clear_active_instances!
124
- end
125
- end
126
- end
127
125
  end
128
126
  end
@@ -1,10 +1,10 @@
1
1
  module NinjaModel
2
2
  module Adapters
3
3
  class AdapterSpecification
4
- attr_accessor :config, :adapter_method
4
+ attr_reader :config, :name
5
5
 
6
- def initialize(config, adapter_method)
7
- @config, @adapter_method = config, adapter_method
6
+ def initialize(config, name)
7
+ @config, @name = config, name
8
8
  end
9
9
  end
10
10
  end
@@ -1,107 +1,27 @@
1
- require 'active_support/concern'
2
- require 'ninja_model/associations/active_record_proxy'
3
- require 'ninja_model/associations/ninja_model_proxy'
4
-
5
- module ActiveRecord
6
- module Associations
7
- module ClassMethods
8
- alias :has_one_without_ninja_model :has_one
9
- def has_one(association_id, options = {})
10
- if ninja_model?(:has_one, options[:class_name] || association_id)
11
- ninja_proxy.handle_association(:has_one, association_id, options)
12
- else
13
- has_one_without_ninja_model(association_id, options)
14
- end
15
- end
16
-
17
- def ninja_proxy
18
- read_inheritable_attribute(:ninja_proxy) || write_inheritable_attribute(:ninja_proxy, NinjaModel::Associations::NinjaModelProxy.new(self))
19
- end
20
-
21
- private
22
-
23
- def ninja_model?(macro, association)
24
- klass = association.to_s.camelize
25
- klass = klass.singularize unless [:has_one, :belongs_to].include?(macro)
26
- klass = klass.constantize
27
- klass.ancestors.include?(NinjaModel::Base)
28
- end
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
-
44
- module Reflection
45
- module ClassMethods
46
- alias :reflect_on_association_without_ninja_model :reflect_on_association
47
- def reflect_on_association(association)
48
- if read_inheritable_attribute(:ninja_proxy) && ninja_proxy.proxy_klass.reflections.include?(association)
49
- ninja_proxy.proxy_klass.reflect_on_association(association)
50
- else
51
- reflect_on_association_without_ninja_model(association)
52
- end
53
- end
54
- end
55
- end
56
- end
57
-
58
1
  module NinjaModel
59
- module Associations
60
- extend ActiveSupport::Concern
61
-
62
- autoload :AssociationProxy, 'ninja_model/associations/association_proxy'
63
- autoload :HasOneAssociation, 'ninja_model/associations/has_one_association'
64
- autoload :HasManyAssociation, 'ninja_model/associations/has_many_association'
65
- autoload :BelongsToAssociation, 'ninja_model/associations/belongs_to_association'
66
2
 
67
-
68
- module ClassMethods
3
+ class Base
4
+ class << self
69
5
  def has_one(association_id, options = {})
70
- if ninja_model?(:has_one, options[:class_name] || association_id)
71
- reflection = create_has_one_reflection(association_id, options)
72
- association_accessor_methods(reflection, HasOneAssociation)
73
- #association_constructor_method(:build, reflection, HasOneAssociation)
74
- #association_constructor_method(:create, reflection, HasOneAssociation)
75
- #configure_dependency_for_has_one(reflection)
76
- else
77
- #puts "Setting up has_one proxy for #{association_id}"
78
- proxy.handle_association(:has_one, association_id, options)
79
- end
6
+ reflection = create_has_one_reflection(association_id, options)
7
+ association_accessor_methods(reflection, Associations::HasOneAssociation)
8
+ # TODO: Implement the build/create association methods
9
+ #association_constructor_method(:build, reflection, HasOneAssociation)
10
+ #association_constructor_method(:create, reflection, HasOneAssociation)
11
+ #configure_dependency_for_has_one(reflection)
80
12
  end
81
13
 
82
14
  def belongs_to(association_id, options = {})
83
- if ninja_model?(:belongs_to, options[:class_name] || association_id)
84
- reflection = create_belongs_to_reflection(association_id, options)
85
- association_accessor_methods(reflection, BelongsToAssociation)
86
- #association_constructor_method(:build, reflection, BelongsToAssociation)
87
- #association_constructor_method(:create, reflection, BelongsToAssociation)
88
- else
89
- proxy.handle_association(:belongs_to, association_id, options)
90
- end
15
+ reflection = create_belongs_to_reflection(association_id, options)
16
+ association_accessor_methods(reflection, Associations::BelongsToAssociation)
17
+ # TODO: Implement the build/create association methods
18
+ #association_constructor_method(:build, reflection, BelongsToAssociation)
19
+ #association_constructor_method(:create, reflection, BelongsToAssociation)
91
20
  end
92
21
 
93
22
  def has_many(association_id, options = {})
94
- if ninja_model?(:has_many, association_id)
95
- reflection = create_has_many_reflection(association_id, options)
96
- collection_accessor_methods(reflection, HasManyAssociation)
97
- #collection_accessor_methods(reflection, HasManyAssociation)
98
- else
99
- proxy.handle_association(:has_many, association_id, options)
100
- end
101
- end
102
-
103
- def proxy
104
- read_inheritable_attribute(:proxy) || write_inheritable_attribute(:proxy, ActiveRecordProxy.new(self))
23
+ reflection = create_has_many_reflection(association_id, options)
24
+ collection_accessor_methods(reflection, Associations::HasManyAssociation)
105
25
  end
106
26
 
107
27
  private
@@ -112,7 +32,6 @@ module NinjaModel
112
32
 
113
33
  def create_has_many_reflection(association, options = {})
114
34
  create_reflection(:has_many, association, options, self)
115
- #options[:extend] = create_extension_modules(association, extension
116
35
  end
117
36
 
118
37
  def create_belongs_to_reflection(association, options = {})
@@ -126,7 +45,7 @@ module NinjaModel
126
45
  if association.nil?
127
46
  association = association_proxy_class.new(self, reflection)
128
47
  retval = association.reload
129
- if retval.nil? and association_proxy_class == BelongsToAssociation
48
+ if retval.nil? and association_proxy_class == Associations::BelongsToAssociation
130
49
  association_instance_set(reflection.name, nil)
131
50
  return nil
132
51
  end
@@ -151,7 +70,7 @@ module NinjaModel
151
70
  end
152
71
 
153
72
  redefine_method("set_#{reflection.name}_target") do |target|
154
- return if target.nil? and association_proxy_class == BelongsToAssociation
73
+ return if target.nil? and association_proxy_class == Associations::BelongsToAssociation
155
74
  association = association_proxy_class.new(self, reflection)
156
75
  association.target = target
157
76
  association_instance_set(reflection.name, association)
@@ -174,6 +93,14 @@ module NinjaModel
174
93
  end
175
94
  end
176
95
  end
96
+ end
97
+
98
+ module Associations
99
+
100
+ autoload :AssociationProxy, 'ninja_model/associations/association_proxy'
101
+ autoload :HasOneAssociation, 'ninja_model/associations/has_one_association'
102
+ autoload :HasManyAssociation, 'ninja_model/associations/has_many_association'
103
+ autoload :BelongsToAssociation, 'ninja_model/associations/belongs_to_association'
177
104
 
178
105
  def association_instance_get(name)
179
106
  ivar = "@#{name}"
@@ -186,13 +113,5 @@ module NinjaModel
186
113
  def association_instance_set(name, association)
187
114
  instance_variable_set("@#{name}", association)
188
115
  end
189
-
190
- def method_missing(method, *args)
191
- if self.class.read_inheritable_attribute(:proxy) && proxy.respond_to?(method)
192
- proxy.send(method, *args)
193
- else
194
- super
195
- end
196
- end
197
116
  end
198
117
  end