objectify 0.0.3 → 0.0.5

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.
Files changed (45) hide show
  1. data/.document +5 -0
  2. data/.gitignore +47 -2
  3. data/.rspec +1 -0
  4. data/Gemfile +1 -1
  5. data/Gemfile.lock +105 -16
  6. data/LICENSE.txt +20 -0
  7. data/README.md +230 -0
  8. data/Rakefile +14 -7
  9. data/lib/objectify.rb +1 -26
  10. data/lib/objectify/config/action.rb +31 -0
  11. data/lib/objectify/config/context.rb +97 -0
  12. data/lib/objectify/config/policies.rb +18 -0
  13. data/lib/objectify/executor.rb +21 -0
  14. data/lib/objectify/injector.rb +39 -0
  15. data/lib/objectify/instantiator.rb +14 -0
  16. data/lib/objectify/instrumentation.rb +12 -0
  17. data/lib/objectify/logging.rb +22 -0
  18. data/lib/objectify/policy_chain_executor.rb +27 -0
  19. data/lib/objectify/rails/application.rb +16 -0
  20. data/lib/objectify/rails/controller.rb +117 -0
  21. data/lib/objectify/rails/helpers.rb +14 -0
  22. data/lib/objectify/rails/log_subscriber.rb +59 -0
  23. data/lib/objectify/rails/railtie.rb +11 -0
  24. data/lib/objectify/rails/renderer.rb +47 -0
  25. data/lib/objectify/rails/routing.rb +97 -0
  26. data/lib/objectify/resolver.rb +27 -0
  27. data/lib/objectify/resolver_locator.rb +73 -0
  28. data/lib/objectify/route.rb +4 -0
  29. data/lib/objectify/version.rb +1 -1
  30. data/objectify.gemspec +13 -8
  31. data/spec/config/action_spec.rb +79 -0
  32. data/spec/config/context_spec.rb +137 -0
  33. data/spec/config/policies_spec.rb +23 -0
  34. data/spec/executor_spec.rb +47 -0
  35. data/spec/injector_spec.rb +88 -0
  36. data/spec/instantiator_spec.rb +22 -0
  37. data/spec/policy_chain_executor_spec.rb +60 -0
  38. data/spec/rails/renderer_spec.rb +63 -0
  39. data/spec/rails/routing_spec.rb +171 -0
  40. data/spec/resolver_locator_spec.rb +109 -0
  41. data/spec/resolver_spec.rb +28 -0
  42. data/spec/route_spec.rb +11 -0
  43. data/spec/spec_helper.rb +13 -5
  44. metadata +142 -62
  45. data/spec/objectify_spec.rb +0 -60
@@ -0,0 +1,137 @@
1
+ require "spec_helper"
2
+ require "objectify/config/context"
3
+
4
+ describe "Objectify::Config::Context" do
5
+ before do
6
+ @policies = stub("Policies")
7
+ @policies_factory = stub("PoliciesFactory", :new => @policies)
8
+
9
+ @context = Objectify::Config::Context.new(@policies_factory)
10
+ end
11
+
12
+ context "appending policy responders" do
13
+ before do
14
+ @context.append_policy_responders :authenticated => :unauthenticated
15
+ @context.append_policy_responders :blocked_profile => :unauthorized
16
+ end
17
+
18
+ it "is cumulative" do
19
+ responders = {:authenticated => :unauthenticated,
20
+ :blocked_profile => :unauthorized}
21
+ @context.policy_responders.should == responders
22
+ end
23
+
24
+ it "retrieves responders by policy name" do
25
+ @context.policy_responder(:authenticated).should == :unauthenticated
26
+ end
27
+
28
+ it "raises an error when a responder is missing" do
29
+ f = lambda { @context.policy_responder(:missing) }
30
+ f.should raise_error
31
+ end
32
+ end
33
+
34
+ context "setting defaults" do
35
+ before do
36
+ @opts = {:policies => [:a, :b], :skip_policies => :c}
37
+ @context.append_defaults @opts
38
+ end
39
+
40
+ it "uses the policies factory to create and store policies" do
41
+ @policies_factory.should have_received(:new).with(@opts)
42
+ @context.policies.should == @policies
43
+ end
44
+ end
45
+
46
+ context "appending actions" do
47
+ before do
48
+ @route = stub("Route")
49
+ @action = stub("Action", :route => @route)
50
+ @context.append_action(@action)
51
+ end
52
+
53
+ it "retrieves actions by route" do
54
+ @context.action(@route).should == @action
55
+ end
56
+
57
+ it "raises an error when no action for a route exists" do
58
+ lambda { @context.action(stub()) }.should raise_error
59
+ end
60
+ end
61
+
62
+ context "when there are no default policies" do
63
+ before do
64
+ @context = Objectify::Config::Context.new
65
+ end
66
+
67
+ it "returns an empty policies objectify" do
68
+ @context.policies.policies.should be_empty
69
+ @context.policies.skip_policies.should be_empty
70
+ end
71
+ end
72
+
73
+ context "appending resolutions" do
74
+ before do
75
+ @locator = stub("ResolverLocator", :add => nil)
76
+ @context = Objectify::Config::Context.new(nil)
77
+ @context.locator = @locator
78
+ @context.append_resolutions :something => String.new
79
+ end
80
+
81
+ it "adds them to a locator it has" do
82
+ @locator.should have_received(:add).with(:something, String.new)
83
+ end
84
+ end
85
+
86
+ context "the legacy_action" do
87
+ before do
88
+ @action = stub("Action")
89
+ @action_factory = stub("ActionFactory", :new => @action)
90
+ @policies = stub("Policies")
91
+ @policies_factory = stub("PoliciesFactory", :new => @policies)
92
+ @route = stub("Route", :resource => :controller, :action => :action)
93
+
94
+ @context = Objectify::Config::Context.new(@policies_factory, @action_factory)
95
+ end
96
+
97
+ context "when there's no legacy action config" do
98
+ before do
99
+ @result = @context.legacy_action(@route)
100
+ end
101
+
102
+ it "creates a new action with the controller and action name and its policies" do
103
+ @action_factory.should have_received(:new).
104
+ with(:controller, :action, {}, @policies)
105
+ end
106
+ end
107
+
108
+ context "when there is a legacy action config" do
109
+ before do
110
+ @action = stub("Action", :route => @route)
111
+ @context.append_action(@action)
112
+ @result = @context.legacy_action(@route)
113
+ end
114
+
115
+ it "returns the existing action" do
116
+ @result.should == @action
117
+ end
118
+ end
119
+ end
120
+
121
+ context "objectify_controller" do
122
+ it "defaults to objectify/rails/objectify" do
123
+ @context.objectify_controller.should == "objectify/rails/objectify"
124
+ end
125
+
126
+ it "is overridable" do
127
+ @context.objectify_controller = "asdf"
128
+ @context.objectify_controller.should == "asdf"
129
+ end
130
+
131
+ it "isn't affected by reloading" do
132
+ @context.objectify_controller = "asdf"
133
+ @context.reload
134
+ @context.objectify_controller.should == "asdf"
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,23 @@
1
+ require "spec_helper"
2
+ require "objectify/config/policies"
3
+
4
+ describe "Objectify::Config::Policies" do
5
+ before do
6
+ @opts = {:policies => [:a, :b, :c], :skip_policies => :b}
7
+ @policies = Objectify::Config::Policies.new(@opts)
8
+ @policies2 = Objectify::Config::Policies.new(:skip_policies => :c)
9
+ end
10
+
11
+ it "extracts the policies from the options" do
12
+ @policies.policies.should == [:a, :b, :c]
13
+ end
14
+
15
+ it "extracts the skip policies from the options" do
16
+ @policies.skip_policies.should == [:b]
17
+ end
18
+
19
+ it "can merge with hashes of policy configs (ignoring nils)" do
20
+ @policies.merge({:skip_policies => :c},
21
+ {:policies => :b}, nil).should == [:a, :b]
22
+ end
23
+ end
@@ -0,0 +1,47 @@
1
+ require "spec_helper"
2
+ require "objectify/executor"
3
+
4
+ describe "Objectify::Executor" do
5
+ before do
6
+ @instance = stub("Instance")
7
+ @instantiator = stub("Instantiator", :call => @instance)
8
+ @injector = stub("Injector", :call => true)
9
+ @executor = Objectify::Executor.new(@injector, @instantiator)
10
+ end
11
+
12
+ context "with a service" do
13
+ before do
14
+ @result = @executor.call(:some, :service)
15
+ end
16
+
17
+ it "creates an instance with the instantiator" do
18
+ @instantiator.should have_received(:call).with(:some, :service)
19
+ end
20
+
21
+ it "calls :call on the instance with the injector" do
22
+ @injector.should have_received(:call).with(@instance, :call)
23
+ end
24
+
25
+ it "returns the result of Injector#call" do
26
+ @result.should be_true
27
+ end
28
+ end
29
+
30
+ context "with a policy" do
31
+ before do
32
+ @result = @executor.call(:some, :policy)
33
+ end
34
+
35
+ it "creates an instance with the instantiator" do
36
+ @instantiator.should have_received(:call).with(:some, :policy)
37
+ end
38
+
39
+ it "calls :allowed? on the instance with the injector" do
40
+ @injector.should have_received(:call).with(@instance, :allowed?)
41
+ end
42
+
43
+ it "returns the result of Injector#call" do
44
+ @result.should be_true
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,88 @@
1
+ require "spec_helper"
2
+ require "objectify/injector"
3
+
4
+ describe "Objectify::Injector" do
5
+ class MyInjectedClass
6
+ attr_reader :some_dependency
7
+
8
+ def initialize(some_dependency)
9
+ @some_dependency = some_dependency
10
+ end
11
+
12
+ def call(some_dependency)
13
+ some_dependency
14
+ end
15
+
16
+ def requires_params(params)
17
+ params
18
+ end
19
+
20
+ def optional_arg(asdf=true)
21
+ end
22
+ end
23
+
24
+ # gotta use a fake resolver here because mocha sucks balls lolruby
25
+ class SimpleResolver
26
+ attr_accessor :name
27
+
28
+ def initialize(something)
29
+ @something = something
30
+ end
31
+
32
+ def call
33
+ @something
34
+ end
35
+ end
36
+
37
+ describe "the simple case" do
38
+ before do
39
+ @dependency = stub("Dependency")
40
+ @resolver = SimpleResolver.new(@dependency)
41
+ @resolver_locator = stub("ResolverLocator", :call => @resolver)
42
+ @injector = Objectify::Injector.new(@resolver_locator)
43
+ end
44
+
45
+ it "can constructor inject based on method name using a simple resolver" do
46
+ @injector.call(MyInjectedClass, :new).some_dependency.should == @dependency
47
+ end
48
+
49
+ it "can method inject based on method name using a simple resolver" do
50
+ object = MyInjectedClass.new(nil)
51
+ @injector.call(object, :call).should == @dependency
52
+ end
53
+
54
+ it "calls the resolver_locator to get the resolver" do
55
+ @injector.call(MyInjectedClass, :new)
56
+ @resolver_locator.should have_received(:call).with(:some_dependency)
57
+ end
58
+
59
+ it "supports optional arguments" do
60
+ obj = MyInjectedClass.new("Asdf")
61
+ lambda { @injector.call(obj, :optional_arg) }.should_not raise_error
62
+ end
63
+ end
64
+
65
+ class ParamsResolver
66
+ def name
67
+ :params
68
+ end
69
+
70
+ def call
71
+ {:some => "params"}
72
+ end
73
+ end
74
+
75
+ context "recursive injection in to resolvers" do
76
+ before do
77
+ @resolver = ParamsResolver.new
78
+ @resolver_locator = stub("ResolverLocator", :call => @resolver)
79
+ @injector = Objectify::Injector.new(@resolver_locator)
80
+ end
81
+
82
+ it "can inject into resolvers" do
83
+ object = MyInjectedClass.new(nil)
84
+ @injector.call(object, :requires_params).should ==
85
+ {:some => "params"}
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,22 @@
1
+ require "spec_helper"
2
+ require "objectify/instantiator"
3
+
4
+ describe "Objectify::Instantiator" do
5
+ class MyService
6
+ end
7
+
8
+ before do
9
+ @service = MyService.new
10
+ @injector = stub("Injector", :call => @service)
11
+ @instantiator = Objectify::Instantiator.new(@injector)
12
+ @result = @instantiator.call(:my, :service)
13
+ end
14
+
15
+ it "returns the result of injector#call" do
16
+ @result.should == @service
17
+ end
18
+
19
+ it "calls the injector with the generated constant" do
20
+ @injector.should have_received(:call).with(MyService, :new)
21
+ end
22
+ end
@@ -0,0 +1,60 @@
1
+ require "spec_helper"
2
+ require "objectify/policy_chain_executor"
3
+
4
+ describe "Objectify::PolicyChainExecutor" do
5
+ before do
6
+ @policies = [:x, :y, :z]
7
+ @action = stub("Action", :policies => @policies)
8
+ @executor = stub("Executor", :call => true)
9
+ @responder = :an_responder
10
+ @context = stub("Context", :policy_responder => @responder)
11
+
12
+ @chain_executor = Objectify::PolicyChainExecutor.new(@executor, @context)
13
+ end
14
+
15
+ context "when all the policies execute successfully" do
16
+ before do
17
+ @result = @chain_executor.call(@action)
18
+ end
19
+
20
+ it "calls each of the policies with the executor" do
21
+ @policies.each do |policy|
22
+ @executor.should have_received(:call).with(policy, :policy)
23
+ end
24
+ end
25
+
26
+ it "doesn't call any responders" do
27
+ @executor.should_not have_received(:call).with(anything, :responder)
28
+ end
29
+
30
+ it "returns true" do
31
+ @result.should be_true
32
+ end
33
+ end
34
+
35
+ context "when one of the policies returns false" do
36
+ before do
37
+ @executor.stubs(:call).with(:y, :policy).returns(false)
38
+ @result = @chain_executor.call(@action)
39
+ end
40
+
41
+ it "calls each of the policies with the executor" do
42
+ @policies[0..1].each do |policy|
43
+ @executor.should have_received(:call).with(policy, :policy)
44
+ end
45
+ end
46
+
47
+ it "doesn't call any the policies after the one that failed" do
48
+ @executor.should_not have_received(:call).with(:z, :policy)
49
+ end
50
+
51
+ it "fetches and calls the policy responder for that policy" do
52
+ @context.should have_received(:policy_responder).with(:y)
53
+ @executor.should have_received(:call).with(:an_responder, :responder)
54
+ end
55
+
56
+ it "returns false" do
57
+ @result.should be_false
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,63 @@
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