objectify 0.2.1 → 0.3.0

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/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # objectify
1
+ # objectify [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/bitlove/objectify)
2
2
 
3
3
  Objectify is a framework that codifies good object oriented design practices for building maintainable rails applications. For more on the motivations that led to objectify, check out this blog post: http://jamesgolick.com/2012/5/22/objectify-a-better-way-to-build-rails-applications.html
4
4
 
@@ -27,7 +27,7 @@ Objectify has two primary components:
27
27
  ```ruby
28
28
  class RequiresLoginPolicy
29
29
  # more on how current user gets injected below
30
- def allowed?(current_user)
30
+ def allowed?(current_user)
31
31
  !current_user.nil?
32
32
  end
33
33
  end
@@ -207,7 +207,7 @@ objectify.resolvers :current_user => "objectify_auth/current_user"
207
207
  ```
208
208
 
209
209
  ### Why did you constructor-inject the User constant in to the CurrentUserResolver?
210
-
210
+
211
211
  Because that makes it possible to test in isolation.
212
212
 
213
213
  ```ruby
@@ -299,10 +299,8 @@ gem "objectify", "> 0"
299
299
  # config/application.rb
300
300
  module MyApp
301
301
  class Application < Rails::Application
302
- require "objectify/rails/application"
303
- require "objectify/rails/controller"
304
302
  # only have to require this if you want objectify logging
305
- require "objectify/rails/log_subscriber"
303
+ require "objectify/rails/log_subscriber"
306
304
  include Objectify::Rails::Application
307
305
  end
308
306
  end
data/Rakefile CHANGED
@@ -11,10 +11,7 @@ rescue Bundler::BundlerError => e
11
11
  end
12
12
  require 'rake'
13
13
 
14
- require 'rspec/core'
15
14
  require 'rspec/core/rake_task'
16
- RSpec::Core::RakeTask.new(:spec) do |spec|
17
- spec.pattern = FileList['spec/**/*_spec.rb']
18
- end
15
+ RSpec::Core::RakeTask.new(:spec)
19
16
 
20
17
  task :default => :spec
@@ -4,7 +4,8 @@ require "objectify/route"
4
4
  module Objectify
5
5
  module Config
6
6
  class Action
7
- attr_reader :resource_name, :name, :route, :policies, :service, :responder
7
+ attr_reader :resource_name, :name, :route, :policies,
8
+ :service, :responder, :namespace
8
9
 
9
10
  def initialize(routing_opts,
10
11
  resource_name, name, options, default_policies,
@@ -13,6 +14,7 @@ module Objectify
13
14
  @resource_name = resource_name
14
15
  @name = name
15
16
  @policies = default_policies.merge(options, options[name])
17
+ @namespace = options[:namespace] || resource_name
16
18
 
17
19
  if options[name]
18
20
  @service = options[name][:service]
@@ -21,11 +23,11 @@ module Objectify
21
23
  end
22
24
 
23
25
  def service
24
- @service ||= [resource_name, name].join("_").to_sym
26
+ @service ||= [namespace, name].join("/")
25
27
  end
26
28
 
27
29
  def responder
28
- @responder ||= [resource_name, name].join("_").to_sym
30
+ @responder ||= [namespace, name].join("/")
29
31
  end
30
32
  end
31
33
  end
@@ -14,20 +14,21 @@ module Objectify
14
14
  def call(object, method)
15
15
  payload = {:object => object, :method => method}
16
16
  instrument("inject.objectify", payload) do |payload|
17
+ namespace = object.respond_to?(:name) && object.name ? object.name.underscore.split("/")[0...-1].join("/") : nil
17
18
  method_obj = method_object(object, method)
18
19
  injectables = method_obj.parameters.map do |reqd, name|
19
- @decoration_context[name] || @config.get(name) if reqd == :req
20
+ @decoration_context[[namespace, name].join("/").to_sym] || @decoration_context[name] || @config.get(name) if reqd == :req
20
21
  end.compact
21
22
  arguments = injectables.map do |type, value|
22
23
  if type == :unknown
23
- type, value = unknown_value_to_injectable(value)
24
+ type, value = unknown_value_to_injectable(namespace, value)
24
25
  end
25
26
 
26
27
  if type == :resolver
27
- resolver_klass = [value, :resolver].join("_").classify.constantize
28
+ resolver_klass = [value, :resolver].join("_").camelize.constantize
28
29
  call(call(resolver_klass, :new), :call)
29
30
  elsif type == :implementation
30
- implementation_klass = value.to_s.classify.constantize
31
+ implementation_klass = value.to_s.camelize.constantize
31
32
  call(implementation_klass, :new)
32
33
  elsif type == :value
33
34
  value
@@ -45,7 +46,7 @@ module Objectify
45
46
  base_name = object.name.underscore.to_sym
46
47
  add_decoration_context(base_name, result)
47
48
  result = @config.decorators(base_name).inject(result) do |memo, decorator|
48
- call(decorator.to_s.classify.constantize, :new).tap do |decorated|
49
+ call(decorator.to_s.camelize.constantize, :new).tap do |decorated|
49
50
  add_decoration_context(base_name, decorated)
50
51
  end
51
52
  end
@@ -65,12 +66,14 @@ module Objectify
65
66
  end
66
67
  end
67
68
 
68
- def unknown_value_to_injectable(value)
69
- [nil, :resolver].each do |suffix|
70
- begin
71
- [value, suffix].compact.join("_").classify.constantize
72
- return [suffix.nil? ? :implementation : suffix, value]
73
- rescue NameError => e
69
+ def unknown_value_to_injectable(namespace, value)
70
+ [namespace, nil].uniq.each do |ns|
71
+ [nil, :resolver].each do |suffix|
72
+ begin
73
+ [ns, [value, suffix].compact.join("_")].compact.join("/").camelize.constantize
74
+ return [suffix.nil? ? :implementation : suffix, [ns, value].compact.join("/")]
75
+ rescue NameError => e
76
+ end
74
77
  end
75
78
  end
76
79
 
@@ -7,7 +7,8 @@ module Objectify
7
7
  end
8
8
 
9
9
  def call(name, type)
10
- klass = [name, type].join("_").classify.constantize
10
+ join_char = type == :policy ? "_" : "/"
11
+ klass = [name, type].join(join_char).classify.constantize
11
12
  @injector.call(klass, :new)
12
13
  end
13
14
  end
@@ -2,7 +2,6 @@ require "objectify/config/policies"
2
2
  require "objectify/executor"
3
3
  require "objectify/policy_chain_executor"
4
4
  require "objectify/instrumentation"
5
- require "objectify/rails/renderer"
6
5
  require "objectify/rails/routes"
7
6
 
8
7
  module Objectify
@@ -37,14 +36,13 @@ module Objectify
37
36
  injectables_context.add_value(:request, request)
38
37
  injectables_context.add_value(:response, response)
39
38
  injectables_context.add_value(:flash, flash)
40
- injectables_context.add_value(:renderer, Renderer.new(self))
41
39
  injectables_context.add_value(:format, objectify_response_collector)
42
40
  injectables_context.add_value(:routes, objectify_routes)
43
41
  end
44
42
  end
45
43
 
46
44
  def objectify_response_collector
47
- @objectify_response_collector ||= ActionController::MimeResponds::Collector.new { default_response }
45
+ @objectify_response_collector ||= ActionController::MimeResponds::Collector.new {}
48
46
  end
49
47
 
50
48
  def objectify_executor
@@ -1,3 +1,3 @@
1
1
  module Objectify
2
- VERSION = "0.2.1"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -19,12 +19,12 @@ Gem::Specification.new do |s|
19
19
  s.require_paths = ["lib"]
20
20
 
21
21
  # specify any dependencies here; for example:
22
- s.add_development_dependency "rspec", "~> 2.4.0"
22
+ s.add_development_dependency "rspec", "~> 2.10.0"
23
23
  s.add_development_dependency "bundler", ">= 1.0.0"
24
24
  s.add_development_dependency "jeweler", "~> 1.6.4"
25
25
  s.add_development_dependency "bourne", "1.0"
26
26
  s.add_development_dependency "mocha", "0.9.8"
27
27
 
28
- s.add_runtime_dependency "rails", ">=3.0.0"
28
+ s.add_runtime_dependency "rails", ">=3.2.5"
29
29
  s.add_runtime_dependency "i18n"
30
30
  end
@@ -20,6 +20,7 @@ describe "Objectify::Config::Action" do
20
20
  }
21
21
 
22
22
  @options = {
23
+ :namespace => :somewhere,
23
24
  :policies => :asdf,
24
25
  :skip_policies => :bsdf,
25
26
  :index => @index_options
@@ -72,12 +73,12 @@ describe "Objectify::Config::Action" do
72
73
  @route_factory)
73
74
  end
74
75
 
75
- it "has a default service of \#{resource_name}_\#{action_name}" do
76
- @action.service.should == :pictures_index
76
+ it "has a default service of \#{resource_name}/\#{action_name}" do
77
+ @action.service.should == "pictures/index"
77
78
  end
78
79
 
79
- it "has a default responder of \#{resource_name}_\#{action_name}" do
80
- @action.responder.should == :pictures_index
80
+ it "has a default responder of \#{resource_name}/\#{action_name}" do
81
+ @action.responder.should == "pictures/index"
81
82
  end
82
83
  end
83
84
  end
@@ -135,4 +135,55 @@ describe "Objectify::Injector" do
135
135
  @injector.call(ToBeDecorated, :new).should be_instance_of(ToBeDecorated)
136
136
  end
137
137
  end
138
+
139
+ module An
140
+ class Service
141
+ attr_reader :canada
142
+
143
+ def initialize(canada)
144
+ @canada = canada
145
+ end
146
+ end
147
+
148
+ class ServiceWithStuff
149
+ attr_reader :service
150
+
151
+ def initialize(service)
152
+ @service = service
153
+ end
154
+ end
155
+
156
+ class ServiceWithOtherStuff
157
+ def initialize(service, my_injected_class)
158
+ @service = service
159
+ @my_injected_class = my_injected_class
160
+ end
161
+ end
162
+
163
+ class Canada
164
+ end
165
+ end
166
+
167
+ context "within a namespace" do
168
+ before do
169
+ @config.stubs(:get).with(:canada).returns([:unknown, :canada])
170
+ @result = @injector.call(An::Service, :new)
171
+ end
172
+
173
+ it "first searches within the namespace to fulfill the dependency" do
174
+ @result.canada.should be_instance_of(An::Canada)
175
+ end
176
+
177
+ it "can decorate" do
178
+ @config.stubs(:decorators).with(:"an/service").returns([:"an/service_with_stuff"])
179
+ @injector.call(An::Service, :new).should be_instance_of(An::ServiceWithStuff)
180
+ end
181
+
182
+ it "can still look up the module chain for decorators" do
183
+ @config.stubs(:decorators).with(:"an/service").returns([:"an/service_with_other_stuff"])
184
+ @config.stubs(:get).with(:my_injected_class).returns([:unknown, :my_injected_class])
185
+ @config.stubs(:get).with(:some_dependency).returns([:value, :asdf])
186
+ @injector.call(An::Service, :new).should be_instance_of(An::ServiceWithOtherStuff)
187
+ end
188
+ end
138
189
  end
@@ -2,21 +2,48 @@ require "spec_helper"
2
2
  require "objectify/instantiator"
3
3
 
4
4
  describe "Objectify::Instantiator" do
5
- class MyService
5
+ module My
6
+ class Service
7
+ end
8
+ end
9
+
10
+ class MyPolicy
6
11
  end
7
12
 
8
13
  before do
9
- @service = MyService.new
10
- @injector = stub("Injector", :call => @service)
14
+ @injector = stub("Injector")
11
15
  @instantiator = Objectify::Instantiator.new(@injector)
12
- @result = @instantiator.call(:my, :service)
13
16
  end
14
17
 
15
- it "returns the result of injector#call" do
16
- @result.should == @service
18
+ context "with a service" do
19
+ before do
20
+ @service = My::Service.new
21
+ @injector.stubs(:call).returns(@service)
22
+ @result = @instantiator.call(:my, :service)
23
+ end
24
+
25
+ it "returns the result of injector#call" do
26
+ @result.should == @service
27
+ end
28
+
29
+ it "locates the service in the supplied namespace and instantiates" do
30
+ @injector.should have_received(:call).with(My::Service, :new)
31
+ end
17
32
  end
18
33
 
19
- it "calls the injector with the generated constant" do
20
- @injector.should have_received(:call).with(MyService, :new)
34
+ context "with a policy" do
35
+ before do
36
+ @policy = MyPolicy.new
37
+ @injector.stubs(:call).returns(@policy)
38
+ @result = @instantiator.call(:my, :policy)
39
+ end
40
+
41
+ it "returns the result of injector#call" do
42
+ @result.should == @policy
43
+ end
44
+
45
+ it "locates the policy namespace and instantiates" do
46
+ @injector.should have_received(:call).with(MyPolicy, :new)
47
+ end
21
48
  end
22
49
  end
@@ -1,15 +1,5 @@
1
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
- $LOAD_PATH.unshift(File.dirname(__FILE__))
3
- require 'rspec'
4
- require "rubygems"
5
- require "rspec"
6
- require "mocha"
7
1
  require "bourne"
8
2
 
9
- # Requires supporting files with custom matchers and macros, etc,
10
- # in ./support/ and its subdirectories.
11
- Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
12
-
13
3
  RSpec.configure do |config|
14
4
  config.mock_with :mocha
15
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: objectify
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,22 +9,22 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-05 00:00:00.000000000 Z
12
+ date: 2012-08-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &70230408805980 !ruby/object:Gem::Requirement
16
+ requirement: &70174896773480 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
20
20
  - !ruby/object:Gem::Version
21
- version: 2.4.0
21
+ version: 2.10.0
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70230408805980
24
+ version_requirements: *70174896773480
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: bundler
27
- requirement: &70230408805480 !ruby/object:Gem::Requirement
27
+ requirement: &70174896772980 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 1.0.0
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70230408805480
35
+ version_requirements: *70174896772980
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: jeweler
38
- requirement: &70230408805020 !ruby/object:Gem::Requirement
38
+ requirement: &70174896772520 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 1.6.4
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70230408805020
46
+ version_requirements: *70174896772520
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: bourne
49
- requirement: &70230408804560 !ruby/object:Gem::Requirement
49
+ requirement: &70174896772060 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - =
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '1.0'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *70230408804560
57
+ version_requirements: *70174896772060
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: mocha
60
- requirement: &70230408804100 !ruby/object:Gem::Requirement
60
+ requirement: &70174896771600 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - =
@@ -65,21 +65,21 @@ dependencies:
65
65
  version: 0.9.8
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *70230408804100
68
+ version_requirements: *70174896771600
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rails
71
- requirement: &70230408803640 !ruby/object:Gem::Requirement
71
+ requirement: &70174896771140 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
75
75
  - !ruby/object:Gem::Version
76
- version: 3.0.0
76
+ version: 3.2.5
77
77
  type: :runtime
78
78
  prerelease: false
79
- version_requirements: *70230408803640
79
+ version_requirements: *70174896771140
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: i18n
82
- requirement: &70230408803260 !ruby/object:Gem::Requirement
82
+ requirement: &70174896770760 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ! '>='
@@ -87,7 +87,7 @@ dependencies:
87
87
  version: '0'
88
88
  type: :runtime
89
89
  prerelease: false
90
- version_requirements: *70230408803260
90
+ version_requirements: *70174896770760
91
91
  description: Objects on rails.
92
92
  email:
93
93
  - jamesgolick@gmail.com
@@ -131,7 +131,6 @@ files:
131
131
  - spec/injector_spec.rb
132
132
  - spec/instantiator_spec.rb
133
133
  - spec/policy_chain_executor_spec.rb
134
- - spec/rails/renderer_spec.rb
135
134
  - spec/rails/routing_spec.rb
136
135
  - spec/route_spec.rb
137
136
  - spec/spec_helper.rb
@@ -170,7 +169,6 @@ test_files:
170
169
  - spec/injector_spec.rb
171
170
  - spec/instantiator_spec.rb
172
171
  - spec/policy_chain_executor_spec.rb
173
- - spec/rails/renderer_spec.rb
174
172
  - spec/rails/routing_spec.rb
175
173
  - spec/route_spec.rb
176
174
  - spec/spec_helper.rb
@@ -1,63 +0,0 @@
1
- require "spec_helper"
2
- require "objectify/rails/renderer"
3
-
4
- describe "Objectify::Rails::Renderer" do
5
- before do
6
- @controller = stub("Controller", :render => nil,
7
- :redirect_to => nil,
8
- :instance_variable_set => nil) # yeah, well.
9
- @renderer = Objectify::Rails::Renderer.new(@controller)
10
- end
11
-
12
- it "delegates template rendering" do
13
- @renderer.template("something.html.erb", :some => :option)
14
- @controller.should have_received(:render).with(:template => "something.html.erb",
15
- :some => :option)
16
- end
17
-
18
- it "delegates action rendering" do
19
- @renderer.action("something.html.erb", :some => :option)
20
- @controller.should have_received(:render).with(:action => "something.html.erb",
21
- :some => :option)
22
- end
23
-
24
- it "delegates partial rendering" do
25
- @renderer.partial("something.html.erb", :some => :option)
26
- @controller.should have_received(:render).with(:partial => "something.html.erb",
27
- :some => :option)
28
- end
29
-
30
- it "delegates rendering nothing" do
31
- @renderer.nothing(:some => :option)
32
- @controller.should have_received(:render).with(:nothing => true,
33
- :some => :option)
34
- end
35
-
36
- it "exposes the full render method" do
37
- @renderer.render(:json => "asdf")
38
- @controller.should have_received(:render).with(:json => "asdf")
39
- end
40
-
41
- it "delegates the respond_to method" do
42
- @responder = stub("Responder")
43
- @responder.stubs(:html).yields
44
- @controller.stubs(:respond_to).yields(@responder)
45
-
46
- @renderer.respond_to do |format|
47
- format.html { }
48
- end
49
-
50
- @responder.should have_received(:html)
51
- end
52
-
53
- it "delegates the redirect_to method" do
54
- @renderer.redirect_to :somewhere
55
- @controller.should have_received(:redirect_to).with(:somewhere)
56
- end
57
-
58
- it "can set the data on the controller" do
59
- @renderer.data("asdf")
60
- @controller.should have_received(:instance_variable_set).
61
- with(:@objectify_data, "asdf")
62
- end
63
- end