cyrax 0.0.3

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/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