cyrax 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Droidlabs
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,31 @@
1
+ # Cyrax
2
+ ![Cyrax](http://images2.wikia.nocookie.net/__cb20121118042055/mk/images/thumb/4/44/CyraxMK9Render.png/322px-CyraxMK9Render.png)
3
+ > Safeties disabled; combat mode engaged.
4
+
5
+ Cyrax is microframework to build layered architecture, one of the core concepts of Domain Driven Design
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'cyrax'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install cyrax
20
+
21
+ ## Usage
22
+
23
+ Look at `example` folder.
24
+
25
+ ## Contributing
26
+
27
+ 1. Fork it
28
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
29
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
30
+ 4. Push to the branch (`git push origin my-new-feature`)
31
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/lib/cyrax.rb ADDED
@@ -0,0 +1,14 @@
1
+ require "cyrax/version"
2
+ require "cyrax/extensions/has_resource.rb"
3
+ require "cyrax/extensions/has_response.rb"
4
+ require "cyrax/extensions/has_callbacks.rb"
5
+ require "cyrax/extensions/has_service.rb"
6
+ require "cyrax/extensions/has_decorator.rb"
7
+ require "cyrax/base.rb"
8
+ require "cyrax/base_resource.rb"
9
+ require "cyrax/response.rb"
10
+ require "cyrax/callbacks.rb"
11
+ require "cyrax/decorator.rb"
12
+
13
+ module Cyrax
14
+ end
data/lib/cyrax/base.rb ADDED
@@ -0,0 +1,12 @@
1
+ require 'has_active_logger'
2
+ class Cyrax::Base
3
+ include HasActiveLogger::Mixin
4
+ include Cyrax::Extensions::HasResponse
5
+
6
+ attr_accessor :params, :accessor
7
+
8
+ def initialize(options = {})
9
+ @accessor = options[:as]
10
+ @params = options[:params]
11
+ end
12
+ end
@@ -0,0 +1,6 @@
1
+ class Cyrax::BaseResource < Cyrax::Base
2
+ include Cyrax::Extensions::HasResource
3
+ include Cyrax::Extensions::HasCallbacks
4
+ include Cyrax::Extensions::HasService
5
+ include Cyrax::Extensions::HasDecorator
6
+ end
@@ -0,0 +1,17 @@
1
+ class Cyrax::Callbacks
2
+ attr_accessor :resource
3
+
4
+ def initialize(resource)
5
+ @resource = resource
6
+ end
7
+
8
+ def before_save; end
9
+ def before_create; end
10
+ def before_update; end
11
+ def before_destroy; end
12
+
13
+ def after_save; end
14
+ def after_create; end
15
+ def after_update; end
16
+ def after_destroy; end
17
+ end
@@ -0,0 +1,13 @@
1
+ class Cyrax::Decorator
2
+ attr_accessor :resource
3
+
4
+ def initialize(resource)
5
+ @resource = resource
6
+ end
7
+
8
+ def method_missing(method, *args, &block)
9
+ return super unless resource.respond_to?(method)
10
+
11
+ resource.send(method, *args, &block)
12
+ end
13
+ end
@@ -0,0 +1,24 @@
1
+ require 'active_support/core_ext/object'
2
+ require 'active_support/core_ext/class'
3
+
4
+ module Cyrax::Extensions
5
+ module HasCallbacks
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ class_attribute :resource_callbacks_handler_class
10
+ end
11
+
12
+ def invoke_callback(name, resource)
13
+ if resource_callbacks_handler_class
14
+ resource_callbacks_handler_class.new(resource).send(name)
15
+ end
16
+ end
17
+
18
+ module ClassMethods
19
+ def callbacks_handler(name, options = {})
20
+ self.resource_callbacks_handler_class = name
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,49 @@
1
+ module Cyrax::Extensions
2
+ module HasDecorator
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ class_attribute :decorator_class_name
7
+ end
8
+
9
+ module ClassMethods
10
+ def decorator(name)
11
+ self.decorator_class_name = name.to_s
12
+ end
13
+ end
14
+
15
+ def decorated_collection
16
+ if decorable?
17
+ build_decorated_collection
18
+ else
19
+ build_collection
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def decorable?
26
+ !self.class.decorator_class_name.nil?
27
+ end
28
+
29
+ def decorator_class
30
+ self.class.decorator_class_name.to_s.classify.constantize
31
+ end
32
+
33
+ def prepare_collection_for_decorate
34
+ collection = build_collection
35
+
36
+ if collection.kind_of?(Array)
37
+ return collection
38
+ elsif collection.respond_to?(:all)
39
+ return collection.all
40
+ else
41
+ return Array.wrap(collection)
42
+ end
43
+ end
44
+
45
+ def build_decorated_collection
46
+ prepare_collection_for_decorate.map{|i| decorator_class.new(i)}
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,69 @@
1
+ require 'active_support'
2
+ module Cyrax::Extensions
3
+ module HasResource
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ class_attribute :resource_name
8
+ class_attribute :resource_class_name
9
+ end
10
+
11
+ def resource_class
12
+ if self.class.resource_class_name
13
+ self.class.resource_class_name.constantize
14
+ else
15
+ resource_name.classify.constantize
16
+ end
17
+ end
18
+
19
+ def resource_scope
20
+ resource_class
21
+ end
22
+
23
+ def collection_name
24
+ resource_name.pluralize
25
+ end
26
+
27
+ def resource_attributes
28
+ filter_attributes(dirty_resource_attributes)
29
+ end
30
+
31
+ def build_resource(id, attributes = {})
32
+ if id.present?
33
+ resource = find_resource(id)
34
+ resource.attributes = attributes
35
+ resource
36
+ else
37
+ resource_scope.new(default_resource_attributes.merge(attributes))
38
+ end
39
+ end
40
+
41
+ def build_collection
42
+ resource_scope
43
+ end
44
+
45
+ def find_resource(id)
46
+ resource_scope.find(id)
47
+ end
48
+
49
+ module ClassMethods
50
+ def resource(name, options = {})
51
+ self.resource_name = name.to_s
52
+ self.resource_class_name = options[:class_name]
53
+ end
54
+ end
55
+
56
+ private
57
+ def dirty_resource_attributes
58
+ params[resource_name] || {}
59
+ end
60
+
61
+ def default_resource_attributes
62
+ {}
63
+ end
64
+
65
+ def filter_attributes(attributes)
66
+ attributes
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,42 @@
1
+ module Cyrax::Extensions
2
+ module HasResponse
3
+ extend ActiveSupport::Concern
4
+
5
+ def add_error(error)
6
+ @_errors ||= []
7
+ @_errors << error
8
+ end
9
+
10
+ def assign_resource(resource_name, resource)
11
+ @_assignments ||= {}
12
+ @_assignments[resource_name.to_sym] = resource
13
+ end
14
+
15
+ def add_error_unless(error, condition)
16
+ add_error(error) unless condition
17
+ end
18
+
19
+ def add_errors_from(model)
20
+ @_errors ||= []
21
+ if model && model.errors.messages.present?
22
+ model.errors.messages.each do |key, value|
23
+ add_error "#{key}: #{value}"
24
+ end
25
+ end
26
+ end
27
+
28
+ def set_message(message)
29
+ @_message = message
30
+ end
31
+
32
+ def respond_with(resource, custom_resource_name=nil)
33
+ name = custom_resource_name||resource_name
34
+ result = respond_to?(:decorator_class) ? decorator_class.new(resource) : resource
35
+ response = Cyrax::Response.new(name, result)
36
+ response.message = @_message
37
+ response.errors = @_errors
38
+ response.assignments = @_assignments
39
+ response
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,55 @@
1
+ module Cyrax::Extensions
2
+ module HasService
3
+ extend ActiveSupport::Concern
4
+
5
+ def collection
6
+ respond_with decorated_collection, collection_name
7
+ end
8
+
9
+ def build
10
+ respond_with build_resource(nil)
11
+ end
12
+
13
+ def create(custom_attributes=nil)
14
+ resource = build_resource(nil, custom_attributes||resource_attributes)
15
+ invoke_callback(:before_create, resource)
16
+ invoke_callback(:before_save, resource)
17
+ if resource.save
18
+ invoke_callback(:after_create, resource)
19
+ invoke_callback(:after_save, resource)
20
+ set_message("#{resource_name.titleize} successfully created")
21
+ else
22
+ add_errors_from(resource)
23
+ end
24
+ respond_with(resource)
25
+ end
26
+
27
+ def read
28
+ respond_with find_resource(params[:id])
29
+ end
30
+ alias_method :edit, :read
31
+
32
+
33
+ def update(custom_attributes=nil)
34
+ resource = build_resource(params[:id], custom_attributes||resource_attributes)
35
+ invoke_callback(:before_update, resource)
36
+ invoke_callback(:before_save, resource)
37
+ if resource.save
38
+ invoke_callback(:after_update, resource)
39
+ invoke_callback(:after_save, resource)
40
+ set_message("#{resource_name.titleize} successfully updated")
41
+ else
42
+ add_errors_from(resource)
43
+ end
44
+ respond_with(resource)
45
+ end
46
+
47
+ def destroy
48
+ resource = find_resource(params[:id])
49
+ invoke_callback(:before_destroy, resource)
50
+ resource.destroy
51
+ invoke_callback(:after_destroy, resource)
52
+ respond_with(resource)
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,46 @@
1
+ class Cyrax::Response
2
+ attr_accessor :message, :errors, :assignments, :result, :resource_name
3
+
4
+ def initialize(resource_name, result)
5
+ @resource_name = resource_name
6
+ @result = result
7
+ @message = nil
8
+ @errors = []
9
+ @assignments = []
10
+ end
11
+
12
+ def with_errors(errors)
13
+ @errors = errors
14
+ self
15
+ end
16
+
17
+ def with_message(message)
18
+ @message = message
19
+ self
20
+ end
21
+
22
+ def success?
23
+ @errors.nil? || @errors.empty?
24
+ end
25
+
26
+ def failure?
27
+ !success?
28
+ end
29
+
30
+ def notice
31
+ message if success?
32
+ end
33
+
34
+ def error
35
+ message || errors.first if failure?
36
+ end
37
+
38
+ def has_error?(error)
39
+ errors && errors.include?(error)
40
+ end
41
+
42
+ def method_missing(method, *args, &block)
43
+ super unless assignments.has_key?(method)
44
+ assignments[method]
45
+ end
46
+ end
@@ -0,0 +1,3 @@
1
+ module Cyrax
2
+ VERSION = "0.0.3"
3
+ end
@@ -0,0 +1,180 @@
1
+ require 'spec_helper'
2
+
3
+ class Foo; end
4
+ module Cyrax
5
+ describe BaseResource do
6
+ describe 'it should behave like resource' do
7
+ context 'class methods' do
8
+ subject { Cyrax::BaseResource }
9
+ it{ should respond_to(:new) }
10
+ end
11
+ context 'instance methods' do
12
+ subject { Cyrax::BaseResource.new }
13
+ it{ should respond_to(:accessor) }
14
+ it{ should respond_to(:params) }
15
+ it{ should respond_to(:resource_name) }
16
+ it{ should respond_to(:resource_class) }
17
+ it{ should respond_to(:resource_scope) }
18
+ it{ should respond_to(:resource_attributes) }
19
+ it{ should respond_to(:build_resource) }
20
+ it{ should respond_to(:build_collection) }
21
+ it{ should respond_to(:find_resource) }
22
+ it{ should respond_to(:assign_resource) }
23
+ it{ should respond_to(:respond_with) }
24
+ it{ should respond_to(:set_message) }
25
+ it{ should respond_to(:add_error) }
26
+ it{ should respond_to(:add_error_unless) }
27
+ it{ should respond_to(:add_errors_from) }
28
+ it{ should respond_to(:invoke_callback) }
29
+ end
30
+ end
31
+
32
+ subject { Cyrax::BaseResource.new }
33
+ let(:resource) { mock.as_null_object }
34
+ let(:collection) { mock }
35
+ before do
36
+ subject.stub!(:params).and_return({id:123})
37
+ subject.stub!(:find_resource).and_return(resource)
38
+ subject.stub!(:resource_name).and_return('foo')
39
+ end
40
+
41
+ describe '#collection' do
42
+ it 'responds with decorated collection' do
43
+ subject.should_receive(:build_collection).and_return(collection)
44
+ subject.should_receive(:respond_with).with(collection, 'foos')
45
+ subject.collection
46
+ end
47
+ end
48
+
49
+ describe '#build' do
50
+ it 'responds with resource' do
51
+ subject.should_receive(:build_resource).with(nil).and_return(resource)
52
+ subject.should_receive(:respond_with).with(resource)
53
+ subject.build
54
+ end
55
+ end
56
+
57
+ describe '#edit' do
58
+ it 'responds with resource' do
59
+ subject.should_receive(:find_resource)
60
+ subject.should_receive(:respond_with).with(resource)
61
+ subject.edit
62
+ end
63
+ end
64
+
65
+ describe '#read' do
66
+ it 'responds with resource' do
67
+ subject.should_receive(:find_resource)
68
+ subject.should_receive(:respond_with).with(resource)
69
+ subject.read
70
+ end
71
+ end
72
+
73
+ describe '#destroy' do
74
+ it 'responds with resource' do
75
+ subject.should_receive(:find_resource)
76
+ subject.should_receive(:respond_with).with(resource)
77
+ subject.destroy
78
+ end
79
+
80
+ it 'destroys resource' do
81
+ resource.should_receive(:destroy)
82
+ subject.destroy
83
+ end
84
+
85
+ it 'invokes callbacks' do
86
+ subject.should_receive(:invoke_callback).with(:before_destroy, resource)
87
+ subject.should_receive(:invoke_callback).with(:after_destroy, resource)
88
+ subject.destroy
89
+ end
90
+ end
91
+
92
+ describe '#create' do
93
+ let(:params) { {foo: 'bar'} }
94
+ before { subject.stub!(:build_resource).and_return(resource) }
95
+ it 'responds with resource' do
96
+ subject.should_receive(:build_resource).with(nil, params)
97
+ subject.should_receive(:respond_with).with(resource)
98
+ subject.create(params)
99
+ end
100
+
101
+ context 'when resource successfully saved' do
102
+ before { resource.stub!(:save).and_return(true) }
103
+
104
+ it 'invokes callbacks' do
105
+ subject.should_receive(:invoke_callback).with(:before_save, resource)
106
+ subject.should_receive(:invoke_callback).with(:before_create, resource)
107
+ subject.should_receive(:invoke_callback).with(:after_save, resource)
108
+ subject.should_receive(:invoke_callback).with(:after_create, resource)
109
+ subject.create(params)
110
+ end
111
+
112
+ it 'sets message' do
113
+ subject.should_receive(:set_message).with('Foo successfully created')
114
+ subject.create(params)
115
+ end
116
+ end
117
+
118
+ context 'when resource could not be saved' do
119
+ before { resource.stub!(:save).and_return(false) }
120
+
121
+ it 'invokes callbacks' do
122
+ subject.should_receive(:invoke_callback).with(:before_save, resource)
123
+ subject.should_receive(:invoke_callback).with(:before_create, resource)
124
+ subject.should_not_receive(:invoke_callback).with(:after_save, resource)
125
+ subject.should_not_receive(:invoke_callback).with(:after_create, resource)
126
+ subject.create(params)
127
+ end
128
+
129
+ it 'sets error messages' do
130
+ subject.should_receive(:add_errors_from).with(resource)
131
+ subject.create(params)
132
+ end
133
+ end
134
+ end
135
+
136
+ describe '#update' do
137
+ let(:params) { {foo: 'bar'} }
138
+ before { subject.stub!(:build_resource).and_return(resource) }
139
+ it 'responds with resource' do
140
+ subject.should_receive(:build_resource).with(123, params)
141
+ subject.should_receive(:respond_with).with(resource)
142
+ subject.update(params)
143
+ end
144
+
145
+ context 'when resource successfully saved' do
146
+ before { resource.stub!(:save).and_return(true) }
147
+
148
+ it 'invokes callbacks' do
149
+ subject.should_receive(:invoke_callback).with(:before_save, resource)
150
+ subject.should_receive(:invoke_callback).with(:before_update, resource)
151
+ subject.should_receive(:invoke_callback).with(:after_save, resource)
152
+ subject.should_receive(:invoke_callback).with(:after_update, resource)
153
+ subject.update(params)
154
+ end
155
+
156
+ it 'sets message' do
157
+ subject.should_receive(:set_message).with('Foo successfully updated')
158
+ subject.update(params)
159
+ end
160
+ end
161
+
162
+ context 'when resource could not be saved' do
163
+ before { resource.stub!(:save).and_return(false) }
164
+
165
+ it 'invokes callbacks' do
166
+ subject.should_receive(:invoke_callback).with(:before_save, resource)
167
+ subject.should_receive(:invoke_callback).with(:before_update, resource)
168
+ subject.should_not_receive(:invoke_callback).with(:after_save, resource)
169
+ subject.should_not_receive(:invoke_callback).with(:after_update, resource)
170
+ subject.update(params)
171
+ end
172
+
173
+ it 'sets error messages' do
174
+ subject.should_receive(:add_errors_from).with(resource)
175
+ subject.update(params)
176
+ end
177
+ end
178
+ end
179
+ end
180
+ end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ module Cyrax
4
+ describe Base do
5
+ describe '#new' do
6
+ subject { Cyrax::Base.new({as: :john, params: {foo: 'bar'}})}
7
+ its(:accessor) { should eq(:john) }
8
+ its(:params) { should eq({foo: 'bar'}) }
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ module Cyrax
4
+ describe Callbacks do
5
+ subject { Cyrax::Callbacks.new(mock) }
6
+
7
+ it { should respond_to(:before_create) }
8
+ it { should respond_to(:after_create) }
9
+
10
+ it { should respond_to(:before_save) }
11
+ it { should respond_to(:after_save) }
12
+
13
+ it { should respond_to(:before_update) }
14
+ it { should respond_to(:after_update) }
15
+
16
+ it { should respond_to(:before_destroy) }
17
+ it { should respond_to(:after_destroy) }
18
+ end
19
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ module Cyrax
4
+ describe Decorator do
5
+ let(:decorable) { mock(foo:'bar') }
6
+ subject { Cyrax::Decorator.new(decorable) }
7
+
8
+ its(:resource) { should eq(decorable) }
9
+
10
+ it 'should translate missing methods to decorable' do
11
+ subject.foo.should eq('bar')
12
+ end
13
+
14
+ it 'should not translate missing methods' do
15
+ expect {
16
+ subject.bar
17
+ }.to raise_error(NoMethodError)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+
3
+ module Cyrax
4
+ describe Cyrax::Extensions::HasCallbacks do
5
+ include Cyrax::Extensions::HasCallbacks
6
+
7
+ describe '#invoke_callback' do
8
+ context 'when callback handler class is not defined' do
9
+ let(:name) { mock }
10
+ let(:resource) { mock }
11
+ before { self.class.stub!(:resource_callbacks_handler_class) }
12
+ it { invoke_callback(name, resource).should be_nil }
13
+ end
14
+
15
+ context 'when callback handler class is defined' do
16
+ let(:name) { "foo" }
17
+ let(:resource) { mock }
18
+ let(:handle_class) { double.as_null_object }
19
+ before { self.class.stub!(:resource_callbacks_handler_class).and_return(handle_class) }
20
+
21
+ it 'initializes handle class instance' do
22
+ handle_class.should_receive(:new).with(resource)
23
+ invoke_callback(name, resource)
24
+ end
25
+
26
+ it 'calls corresponding method on instance' do
27
+ instance = double.as_null_object
28
+ handle_class.stub!(:new).and_return(instance)
29
+ instance.should_receive(:foo)
30
+ invoke_callback(name, resource)
31
+ end
32
+ end
33
+ end
34
+
35
+ describe '#callbacks_handler' do
36
+ it 'should define callbacks handler class' do
37
+ self.class.callbacks_handler('Foo')
38
+ self.class.resource_callbacks_handler_class.should eq('Foo')
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,102 @@
1
+ require 'spec_helper'
2
+
3
+ class Foo;
4
+ attr_accessor :a
5
+ def initialize(arg)
6
+ @a = arg
7
+ end
8
+
9
+ def ==(other)
10
+ self.a == other.a
11
+ end
12
+ end
13
+
14
+ module Cyrax
15
+ describe Cyrax::Extensions::HasDecorator do
16
+ include Cyrax::Extensions::HasDecorator
17
+
18
+ describe 'class attributes' do
19
+ subject { self.class }
20
+ it { should respond_to(:decorator_class_name) }
21
+ end
22
+
23
+ describe 'class methods' do
24
+ describe '#decorator' do
25
+ before { self.class.decorator(:foo) }
26
+ subject { self }
27
+
28
+ its(:decorator_class_name) { should eq('foo') }
29
+ end
30
+ end
31
+
32
+ describe 'instance methods' do
33
+ subject { self }
34
+
35
+ describe '#decorator_class' do
36
+ before { self.class.decorator(:foo) }
37
+ its(:decorator_class) { should eq(Foo) }
38
+ end
39
+
40
+ describe '#decorable?' do
41
+ context 'when `decorator_class_name` present' do
42
+ before { self.class.decorator(:foo) }
43
+ its(:decorable?) { should be_true }
44
+ end
45
+
46
+ context 'when `decorator_class_name` empty' do
47
+ its(:decorable?) { should be_false }
48
+ end
49
+ end
50
+
51
+ describe '#decorated_collection' do
52
+ context 'when `decorable?`' do
53
+ before { subject.stub!(:decorable?).and_return(true) }
54
+ it 'should return decorated result' do
55
+ subject.should_receive(:build_decorated_collection)
56
+ subject.decorated_collection
57
+ end
58
+ end
59
+ context 'when not `decorable?`' do
60
+ before { subject.stub!(:decorable?).and_return(false) }
61
+ it 'should return raw result' do
62
+ subject.should_not_receive(:build_decorated_collection)
63
+ subject.should_receive(:build_collection)
64
+ subject.decorated_collection
65
+ end
66
+ end
67
+ end
68
+
69
+ describe '#build_decorated_collection' do
70
+ before do
71
+ self.class.decorator(:foo)
72
+ subject.stub!(:prepare_collection_for_decorate).and_return([:bar])
73
+ end
74
+
75
+ it 'returns array of decorator instances' do
76
+ subject.send(:build_decorated_collection).should eq([Foo.new(:bar)])
77
+ end
78
+ end
79
+
80
+ describe '#prepare_collection_for_decorate' do
81
+ subject { self.send(:prepare_collection_for_decorate) }
82
+
83
+ context 'when #build_collection returns array' do
84
+ before { self.stub!(:build_collection).and_return([:bar]) }
85
+ it { should eq([:bar]) }
86
+ end
87
+
88
+ context 'when #build_collection returns any object except array' do
89
+ before { self.stub!(:build_collection).and_return(:bar) }
90
+ it { should eq([:bar]) }
91
+ end
92
+
93
+ context 'when #build_collection returns any object which responds to #all method' do
94
+ let(:obj) { mock(:all => [:bar] ) }
95
+ before { self.stub!(:build_collection).and_return(obj) }
96
+
97
+ it { should eq([:bar]) }
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,138 @@
1
+ require 'spec_helper'
2
+
3
+ class Bar; end
4
+ class Foo; end
5
+
6
+ module Cyrax
7
+ describe Cyrax::Extensions::HasResource do
8
+ include Cyrax::Extensions::HasResource
9
+
10
+ describe 'class attributes' do
11
+ subject { self.class }
12
+ it { should respond_to(:resource_name) }
13
+ it { should respond_to(:resource_class_name) }
14
+ end
15
+
16
+ describe 'class methods' do
17
+ describe '#resource' do
18
+ before { self.class.resource(:foo, class_name:'bar', name:'bazz') }
19
+ subject { self }
20
+
21
+ its(:resource_name) { should eq('foo') }
22
+ its(:resource_class_name) { should eq('bar') }
23
+ end
24
+ end
25
+
26
+ describe 'instance methods' do
27
+ subject { self }
28
+
29
+ describe '#resource_name' do
30
+ before { self.class.resource(:foo) }
31
+ its(:resource_name) { should eq('foo') }
32
+ end
33
+
34
+ describe '#collection_name' do
35
+ before { self.class.resource(:foo) }
36
+ its(:collection_name) { should eq('foos') }
37
+ end
38
+
39
+ describe '#resource_class' do
40
+ context 'when `class_name` option is supplied' do
41
+ before { self.class.resource(:foo, class_name:'Bar') }
42
+ its(:resource_class) { should eq(Bar) }
43
+ end
44
+
45
+ context 'when `class_name` option is omited' do
46
+ before { self.class.resource(:foo) }
47
+ its(:resource_class) { should eq(Foo) }
48
+ end
49
+ end
50
+
51
+ describe '#resource_scope' do
52
+ before { subject.stub!(:resource_class).and_return(Foo) }
53
+ its(:resource_scope) { should eq(Foo) }
54
+ end
55
+
56
+ describe '#build_collection' do
57
+ before { subject.stub!(:resource_class).and_return(Foo) }
58
+ its(:build_collection) { should eq(Foo) }
59
+ end
60
+
61
+ describe '#find_resource' do
62
+ let(:resource_scope) { mock }
63
+ before { subject.stub!(:resource_scope).and_return(resource_scope) }
64
+ it 'finds resource by id' do
65
+ allow_message_expectations_on_nil
66
+ resource_scope.should_receive(:find).with(123)
67
+ subject.find_resource(123)
68
+ end
69
+ end
70
+
71
+ describe '#build_resource' do
72
+ context 'when id is nil' do
73
+ let(:resource_scope) { mock }
74
+ before { subject.stub!(:resource_scope).and_return(resource_scope) }
75
+ it 'initializes new object' do
76
+ allow_message_expectations_on_nil
77
+ resource_scope.should_receive(:new).with({foo: 'bar'})
78
+ subject.build_resource(nil, {foo: 'bar'})
79
+ end
80
+ end
81
+ context 'when id is present' do
82
+ let(:resource) { mock.as_null_object }
83
+ it 'finds resource' do
84
+ subject.should_receive(:find_resource).with(123).and_return(resource)
85
+ subject.build_resource(123, {foo: 'bar'})
86
+ end
87
+
88
+ it 'assigns provided attributes' do
89
+ subject.stub!(:find_resource).and_return(resource)
90
+ resource.should_receive(:attributes=).with({foo: 'bar'})
91
+ subject.build_resource(123, {foo: 'bar'})
92
+ end
93
+ end
94
+ end
95
+
96
+ describe '#resource_attributes' do
97
+ let(:dirty_resource_attributes) { mock }
98
+ before { subject.stub!(:dirty_resource_attributes).and_return(dirty_resource_attributes)}
99
+ it 'filters dirty attributes' do
100
+ subject.should_receive(:filter_attributes).with(dirty_resource_attributes)
101
+ subject.resource_attributes
102
+ end
103
+ end
104
+ end
105
+
106
+ describe 'private methods' do
107
+ subject { self }
108
+ describe '#dirty_resource_attributes' do
109
+ context 'when params are present' do
110
+ it 'should return from params by resource_name' do
111
+ subject.stub!(:resource_name).and_return(:foo)
112
+ subject.stub!(:params).and_return({foo: {bar: 'bazz'}})
113
+ subject.send(:dirty_resource_attributes).should eq({bar: 'bazz'})
114
+ end
115
+ end
116
+ context 'when there are no params' do
117
+ it 'should return empty hash' do
118
+ subject.stub!(:resource_name).and_return(:foo)
119
+ subject.stub!(:params).and_return({})
120
+ subject.send(:dirty_resource_attributes).should eq({})
121
+ end
122
+ end
123
+ end
124
+ describe '#default_resource_attributes' do
125
+ it 'should return empty hash by default' do
126
+ subject.send(:default_resource_attributes).should eq({})
127
+ end
128
+ end
129
+
130
+ describe '#filter_attributes' do
131
+ it 'should return supplied attributes by default' do
132
+ subject.send(:filter_attributes, {foo: 'bar'}).should eq({foo: 'bar'})
133
+ end
134
+ end
135
+ end
136
+
137
+ end
138
+ end
@@ -0,0 +1,74 @@
1
+ require 'spec_helper'
2
+
3
+ module Cyrax
4
+ describe Cyrax::Extensions::HasResponse do
5
+ include Cyrax::Extensions::HasResponse
6
+
7
+ subject { self }
8
+
9
+ describe '#set_message' do
10
+ it 'should set message' do
11
+ subject.set_message('foo')
12
+ subject.instance_variable_get(:@_message).should eq('foo')
13
+ end
14
+ end
15
+
16
+ describe '#add_error' do
17
+ it 'should add error' do
18
+ subject.add_error('foo')
19
+ subject.instance_variable_get(:@_errors).should include('foo')
20
+ end
21
+ end
22
+
23
+ describe '#add_error_unless' do
24
+ it 'should add error when condition false' do
25
+ subject.add_error_unless('foo', 1==0)
26
+ subject.instance_variable_get(:@_errors).should include('foo')
27
+ end
28
+
29
+ it 'should not add error when condition true' do
30
+ subject.add_error_unless('foo', 1==1)
31
+ subject.instance_variable_get(:@_errors).should be_nil
32
+ end
33
+ end
34
+
35
+ describe '#add_errors_from' do
36
+ let(:messages) { [[:foo, 'bar'], [:bar, 'bazz']]}
37
+ let(:errors) { mock(messages: messages)}
38
+ let(:model) { mock(errors: errors) }
39
+
40
+ it 'should add errors from model error messages' do
41
+ subject.add_errors_from(model)
42
+ subject.instance_variable_get(:@_errors).should eq(['foo: bar', 'bar: bazz'])
43
+ end
44
+ end
45
+
46
+ describe '#assign_resource' do
47
+ it 'should set assignments' do
48
+ subject.assign_resource('foo', 'bar')
49
+ subject.instance_variable_get(:@_assignments).should eq({foo: 'bar'})
50
+ end
51
+ end
52
+
53
+ describe '#respond_with' do
54
+ before { subject.stub!(:resource_name).and_return(:foo) }
55
+ it 'calls Cyrax::Response' do
56
+ Cyrax::Response.should_receive(:new).with(:foo, 'bar').and_return(mock.as_null_object)
57
+ subject.respond_with('bar')
58
+ end
59
+
60
+ it 'should return Cyrax::Response instance' do
61
+ subject.respond_with('bar').should be_a_kind_of(Cyrax::Response)
62
+ end
63
+
64
+ it 'should assign message, errors and additional assignments to response object' do
65
+ response = mock
66
+ Cyrax::Response.should_receive(:new).and_return(response)
67
+ response.should_receive(:message=)
68
+ response.should_receive(:errors=)
69
+ response.should_receive(:assignments=)
70
+ subject.respond_with('bar')
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,97 @@
1
+ require 'spec_helper'
2
+
3
+ module Cyrax
4
+ describe Response do
5
+ subject { Cyrax::Response.new('some_resource', 'some_result')}
6
+
7
+ describe '#with_message' do
8
+ before { subject.with_message('some message') }
9
+ it { should be_kind_of(Cyrax::Response) }
10
+ its(:message) { should be }
11
+ its(:message) { should eq('some message') }
12
+ end
13
+
14
+ describe '#with_errors' do
15
+ before { subject.with_errors(['some', 'errors']) }
16
+ it { should be_kind_of(Cyrax::Response) }
17
+ its(:errors) { should be }
18
+ its(:errors) { should eq(['some', 'errors']) }
19
+ end
20
+
21
+ describe '#success?' do
22
+ context 'when there are no errors' do
23
+ before { subject.with_errors([]) }
24
+ its(:success?) { should be_true }
25
+ end
26
+
27
+ context 'when there are errors' do
28
+ before { subject.with_errors(['some', 'errors']) }
29
+ its(:success?) { should be_false }
30
+ end
31
+ end
32
+
33
+ describe '#failure?' do
34
+ context 'when there are no errors' do
35
+ before { subject.with_errors([]) }
36
+ its(:failure?) { should be_false }
37
+ end
38
+
39
+ context 'when there are errors' do
40
+ before { subject.with_errors(['some', 'errors']) }
41
+ its(:failure?) { should be_true }
42
+ end
43
+ end
44
+
45
+ describe '#notice' do
46
+ before { subject.with_message('some message') }
47
+ context 'when there are no errors' do
48
+ before { subject.with_errors([]) }
49
+ its(:notice) { should be }
50
+ its(:notice) { should eq('some message') }
51
+ end
52
+
53
+ context 'when there are errors' do
54
+ before { subject.with_errors(['some', 'errors']) }
55
+ its(:notice) { should be_nil }
56
+ end
57
+ end
58
+
59
+ describe '#error' do
60
+ context 'when there are no errors' do
61
+ before { subject.with_errors([]) }
62
+ its(:error) { should be_nil }
63
+ end
64
+
65
+ context 'when there are errors' do
66
+ before { subject.with_errors(['some', 'message']) }
67
+ its(:error) { should be }
68
+ its(:error) { should eq('some') }
69
+ end
70
+
71
+ context 'when message is present' do
72
+ before { subject.with_message('some message').with_errors(['some', 'message']) }
73
+ its(:error) { should be }
74
+ its(:error) { should eq('some message') }
75
+ end
76
+ end
77
+
78
+ describe '#has_error?' do
79
+ context 'when there are no errors' do
80
+ before { subject.with_errors([]) }
81
+ specify { subject.has_error?('foo').should be_false }
82
+ end
83
+
84
+ context 'when there are errors' do
85
+ before { subject.with_errors(['some', 'message']) }
86
+ specify { subject.has_error?('some').should be_true }
87
+ specify { subject.has_error?('foo').should be_false }
88
+ end
89
+ end
90
+
91
+ describe '#method_missing' do
92
+ before { subject.assignments = {foo: 'bar'} }
93
+ its(:foo) { should eq('bar') }
94
+ specify { expect{ subject.bar }.to raise_error(NoMethodError) }
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,6 @@
1
+ if ENV['COVERAGE']
2
+ require 'simplecov'
3
+ SimpleCov.start
4
+ end
5
+
6
+ require 'cyrax'
metadata ADDED
@@ -0,0 +1,128 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cyrax
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Droidlabs
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-05-16 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: activesupport
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: has_active_logger
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rspec
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: Small library for adding service layer to Rails projects
63
+ email:
64
+ executables: []
65
+ extensions: []
66
+ extra_rdoc_files: []
67
+ files:
68
+ - lib/cyrax/base.rb
69
+ - lib/cyrax/base_resource.rb
70
+ - lib/cyrax/callbacks.rb
71
+ - lib/cyrax/decorator.rb
72
+ - lib/cyrax/extensions/has_callbacks.rb
73
+ - lib/cyrax/extensions/has_decorator.rb
74
+ - lib/cyrax/extensions/has_resource.rb
75
+ - lib/cyrax/extensions/has_response.rb
76
+ - lib/cyrax/extensions/has_service.rb
77
+ - lib/cyrax/response.rb
78
+ - lib/cyrax/version.rb
79
+ - lib/cyrax.rb
80
+ - LICENSE.txt
81
+ - Rakefile
82
+ - README.md
83
+ - spec/cyrax/base_resource_spec.rb
84
+ - spec/cyrax/base_spec.rb
85
+ - spec/cyrax/callbacks_spec.rb
86
+ - spec/cyrax/decorator_spec.rb
87
+ - spec/cyrax/extensions/has_callbacks_spec.rb
88
+ - spec/cyrax/extensions/has_decorator_spec.rb
89
+ - spec/cyrax/extensions/has_resource_spec.rb
90
+ - spec/cyrax/extensions/has_response_spec.rb
91
+ - spec/cyrax/response_spec.rb
92
+ - spec/spec_helper.rb
93
+ homepage:
94
+ licenses:
95
+ - MIT
96
+ post_install_message:
97
+ rdoc_options: []
98
+ require_paths:
99
+ - lib
100
+ required_ruby_version: !ruby/object:Gem::Requirement
101
+ none: false
102
+ requirements:
103
+ - - ! '>='
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ required_rubygems_version: !ruby/object:Gem::Requirement
107
+ none: false
108
+ requirements:
109
+ - - ! '>='
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ requirements: []
113
+ rubyforge_project:
114
+ rubygems_version: 1.8.25
115
+ signing_key:
116
+ specification_version: 3
117
+ summary: Small library for adding service layer to Rails projects
118
+ test_files:
119
+ - spec/cyrax/base_resource_spec.rb
120
+ - spec/cyrax/base_spec.rb
121
+ - spec/cyrax/callbacks_spec.rb
122
+ - spec/cyrax/decorator_spec.rb
123
+ - spec/cyrax/extensions/has_callbacks_spec.rb
124
+ - spec/cyrax/extensions/has_decorator_spec.rb
125
+ - spec/cyrax/extensions/has_resource_spec.rb
126
+ - spec/cyrax/extensions/has_response_spec.rb
127
+ - spec/cyrax/response_spec.rb
128
+ - spec/spec_helper.rb