objectify 0.0.3 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +47 -2
- data/.rspec +1 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +105 -16
- data/LICENSE.txt +20 -0
- data/README.md +230 -0
- data/Rakefile +14 -7
- data/lib/objectify.rb +1 -26
- data/lib/objectify/config/action.rb +31 -0
- data/lib/objectify/config/context.rb +97 -0
- data/lib/objectify/config/policies.rb +18 -0
- data/lib/objectify/executor.rb +21 -0
- data/lib/objectify/injector.rb +39 -0
- data/lib/objectify/instantiator.rb +14 -0
- data/lib/objectify/instrumentation.rb +12 -0
- data/lib/objectify/logging.rb +22 -0
- data/lib/objectify/policy_chain_executor.rb +27 -0
- data/lib/objectify/rails/application.rb +16 -0
- data/lib/objectify/rails/controller.rb +117 -0
- data/lib/objectify/rails/helpers.rb +14 -0
- data/lib/objectify/rails/log_subscriber.rb +59 -0
- data/lib/objectify/rails/railtie.rb +11 -0
- data/lib/objectify/rails/renderer.rb +47 -0
- data/lib/objectify/rails/routing.rb +97 -0
- data/lib/objectify/resolver.rb +27 -0
- data/lib/objectify/resolver_locator.rb +73 -0
- data/lib/objectify/route.rb +4 -0
- data/lib/objectify/version.rb +1 -1
- data/objectify.gemspec +13 -8
- data/spec/config/action_spec.rb +79 -0
- data/spec/config/context_spec.rb +137 -0
- data/spec/config/policies_spec.rb +23 -0
- data/spec/executor_spec.rb +47 -0
- data/spec/injector_spec.rb +88 -0
- data/spec/instantiator_spec.rb +22 -0
- data/spec/policy_chain_executor_spec.rb +60 -0
- data/spec/rails/renderer_spec.rb +63 -0
- data/spec/rails/routing_spec.rb +171 -0
- data/spec/resolver_locator_spec.rb +109 -0
- data/spec/resolver_spec.rb +28 -0
- data/spec/route_spec.rb +11 -0
- data/spec/spec_helper.rb +13 -5
- metadata +142 -62
- 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
|