objectify 0.0.3 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
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