services 4.1.0 → 4.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +4 -0
- data/Guardfile +1 -1
- data/README.md +78 -36
- data/lib/services.rb +5 -0
- data/lib/services/modules/uniqueness_checker.rb +6 -6
- data/lib/services/version.rb +1 -1
- data/spec/services/base_spec.rb +2 -2
- data/spec/services/logger/redis_spec.rb +1 -1
- data/spec/services/modules/uniqueness_checker_spec.rb +1 -1
- data/spec/spec_helper.rb +4 -6
- data/spec/support/activerecord_models_and_services.rb +9 -3
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cd7dc93d539be1dfb493ae76fa3517df9f91c50e
|
4
|
+
data.tar.gz: 6c5c5c79fb229e7c1ab98d68ede41939b800e8d2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 470ab654cddf1cc75439e0301090865ec6269f31acd76e42d0e614ecbf003373330954d3f1b03376eb3eda59815bf6513cfab1cc7dc79deab9f002e4b4c32ea9
|
7
|
+
data.tar.gz: 4ff35e833918ff1c6269388242bcbdaa4d57f9eaa38f25a1c34450766ceaaf82f12180e964fd39636bd490d917d5461d5ed07eb694a7ceaff76f3ca432ffc31f
|
data/.travis.yml
CHANGED
data/Guardfile
CHANGED
@@ -15,7 +15,7 @@ module ::Guard
|
|
15
15
|
REDIS_CLI = SPEC_SUPPORT_DIR.join('redis-cli')
|
16
16
|
REDIS_PIDFILE = SPEC_SUPPORT_DIR.join('redis.pid')
|
17
17
|
REDIS_LOGFILE = SPEC_SUPPORT_DIR.join('log', 'redis.log')
|
18
|
-
REDIS_PORT =
|
18
|
+
REDIS_PORT = 6379
|
19
19
|
|
20
20
|
def self.options_to_string(options)
|
21
21
|
options.map { |k, v| "-#{'-' if k.length > 1}#{k} #{v}" }.join(' ')
|
data/README.md
CHANGED
@@ -5,17 +5,17 @@
|
|
5
5
|
[![Dependency Status](https://gemnasium.com/krautcomputing/services.png)](https://gemnasium.com/krautcomputing/services)
|
6
6
|
[![Code Climate](https://codeclimate.com/github/krautcomputing/services.png)](https://codeclimate.com/github/krautcomputing/services)
|
7
7
|
|
8
|
-
Services is a
|
8
|
+
Services is a collection of modules and base classes that let you simply add a service layer to your Rails app.
|
9
9
|
|
10
10
|
## Motivation
|
11
11
|
|
12
|
-
A lot has been written about service layers
|
12
|
+
A lot has been written about service layers (service objects, SOA, etc.) for Rails. There are of course advantages and disadvantages, but after using Services since 2013 in several Rails apps, I must say that in my opinion the advantages far outweigh the disadvantages.
|
13
13
|
|
14
|
-
**The biggest benefit you get when using a service layer is that it gets much easier to reason about your application, find a bug, or implement new features, when all your business logic is in services, not scattered in models, controllers, helpers etc.**
|
14
|
+
**The biggest benefit you get when using a service layer, in my opinion, is that it gets so much easier to reason about your application, find a bug, or implement new features, when all your business logic is in services, not scattered in models, controllers, helpers etc.**
|
15
15
|
|
16
16
|
## Usage
|
17
17
|
|
18
|
-
For disambiguation: when
|
18
|
+
For disambiguation: in this README, when you read "Services" with a uppercase "S", this gem is meant, whereas with "services", well, the plural of service is meant.
|
19
19
|
|
20
20
|
### Requirements
|
21
21
|
|
@@ -23,17 +23,17 @@ For disambiguation: when I write "Services" with a uppercase "S", I mean this ge
|
|
23
23
|
|
24
24
|
#### Rails >= 3.2
|
25
25
|
|
26
|
-
#### Redis
|
26
|
+
#### Redis >= 2.8
|
27
27
|
|
28
|
-
Redis is used at several points, e.g. to store information about the currently running services, so you can
|
28
|
+
Redis is used at several points, e.g. to store information about the currently running services, so you can enforce uniqueness for specific services, i.e. make sure no more than one instance of such a service is executed simultaneously.
|
29
29
|
|
30
|
-
#### Postgres
|
30
|
+
#### Postgres (optional)
|
31
31
|
|
32
|
-
The SQL that `Services::Query` (discussed further down) generates is optimized for Postgres. It might work with other databases but it's not guaranteed. If you're not using Postgres, don't use `Services::Query` or, even better, submit a [pull request](https://github.com/krautcomputing/services/issues) that fixes it to work with your database!
|
32
|
+
The SQL that `Services::Query` (discussed further down) generates is optimized for Postgres. It might work with other databases but it's not guaranteed. If you're not using Postgres, you can still use all other parts of Services, just don't use `Services::Query` or, even better, submit a [pull request](https://github.com/krautcomputing/services/issues) that fixes it to work with your database!
|
33
33
|
|
34
34
|
#### Sidekiq (optional)
|
35
35
|
|
36
|
-
To process services in the background, Services uses [Sidekiq](https://github.com/mperham/sidekiq).
|
36
|
+
To process services in the background, Services uses [Sidekiq](https://github.com/mperham/sidekiq). If you don't need background processing, you can still use Services without Sidekiq. When you then try to enqueue a service for background processing, an exception will be raised. If you use Sidekiq, make sure to load the Services gem after the Sidekiq gem.
|
37
37
|
|
38
38
|
### Basic principles
|
39
39
|
|
@@ -41,22 +41,23 @@ Services is based on a couple of basic principles around what a service should b
|
|
41
41
|
|
42
42
|
A service...
|
43
43
|
|
44
|
-
* does one thing and does it well (Unix philosophy)
|
45
|
-
* can be run synchronously (in the foreground) or asynchronously (in the background)
|
46
|
-
* can be configured as "unique", meaning only one instance of it should be run at any time
|
44
|
+
* does only one thing and does it well (Unix philosophy)
|
45
|
+
* can be run synchronously (i.e. blocking/in the foreground) or asynchronously (i.e. non-blocking/in the background)
|
46
|
+
* can be configured as "unique", meaning only one instance of it should be run at any time (including or ignoring parameters)
|
47
47
|
* logs all the things (start time, end time, duration, caller, exceptions etc.)
|
48
|
-
* has its own exception class(es)
|
49
|
-
*
|
48
|
+
* has its own exception class(es) which all exceptions that might be raised inherit from
|
49
|
+
* does not care whether certain parameters are objects or object IDs
|
50
50
|
|
51
|
-
Apart from these basic principles, you
|
51
|
+
Apart from these basic principles, you are free to implement the actual logic in a service any way you want.
|
52
52
|
|
53
53
|
### Conventions
|
54
54
|
|
55
|
-
Follow these conventions when using Services in your Rails app:
|
55
|
+
Follow these conventions when using Services in your Rails app, and you'll be fine:
|
56
56
|
|
57
|
-
* Let your services inherit from `Services::Base`
|
57
|
+
* Let your services inherit from `Services::Base`
|
58
|
+
* Let your query objects inherit from `Services::Query`
|
58
59
|
* Put your services in `app/services/`
|
59
|
-
* Namespace your services with the model they operate on and give them verb names, e.g. `app/services/users/delete.rb` defines `Services::Users::Delete`. If a service operates on multiple models or no models at all, don't namespace them (`Services::DoStuff`) or namespace them by logical groups unrelated to models (`Services::Maintenance::CleanOldStuff`, `Services::Maintenance::SendDailySummary`, etc.)
|
60
|
+
* Namespace your services with the model they operate on and give them "verb names", e.g. `app/services/users/delete.rb` defines `Services::Users::Delete`. If a service operates on multiple models or no models at all, don't namespace them (`Services::DoStuff`) or namespace them by logical groups unrelated to models (`Services::Maintenance::CleanOldStuff`, `Services::Maintenance::SendDailySummary`, etc.)
|
60
61
|
* Some services call other services. Try to not combine multiple calls to other services and business logic in one service. Instead, some services should contain only business logic and other services only a bunch of service calls but no (or little) business logic. This keeps your services nice and modular.
|
61
62
|
|
62
63
|
### Configuration
|
@@ -66,8 +67,9 @@ You can/should configure Services in an initializer:
|
|
66
67
|
```ruby
|
67
68
|
# config/initializers/services.rb
|
68
69
|
Services.configure do |config|
|
69
|
-
config.logger = Services::Logger::Redis.new(Redis.new)
|
70
|
-
config.redis = Redis.new
|
70
|
+
config.logger = Services::Logger::Redis.new(Redis.new) # see Logging
|
71
|
+
config.redis = Redis.new # optional, if Redis.current is defined. Otherwise it is recommended to use
|
72
|
+
# a [connection pool](https://github.com/mperham/connection_pool).
|
71
73
|
end
|
72
74
|
```
|
73
75
|
|
@@ -80,9 +82,15 @@ By default, Rails expects `app/services/users/delete.rb` to define `Users::Delet
|
|
80
82
|
config.autoload_paths += [config.root.join('app')]
|
81
83
|
```
|
82
84
|
|
83
|
-
|
85
|
+
This looks as if it might break things, but I've never had any problems with it.
|
86
|
+
|
87
|
+
### Services::Base
|
88
|
+
|
89
|
+
`Services::Base` is the base class you should use for all your services. It gives you a couply of helper methods and defines a custom exception class for you.
|
84
90
|
|
85
|
-
|
91
|
+
Read [the source](lib/services/base.rb) to understand what it does in more detail.
|
92
|
+
|
93
|
+
The following example service takes one or more users or user IDs as an argument and deletes the users:
|
86
94
|
|
87
95
|
```ruby
|
88
96
|
module Services
|
@@ -91,6 +99,9 @@ module Services
|
|
91
99
|
def call(ids_or_objects)
|
92
100
|
users = find_objects(ids_or_objects)
|
93
101
|
users.each do |user|
|
102
|
+
if user.posts.any?
|
103
|
+
raise Error, "User #{user.id} has one or more posts, refusing to delete."
|
104
|
+
end
|
94
105
|
user.destroy
|
95
106
|
Mailer.user_deleted(user).deliver
|
96
107
|
end
|
@@ -105,37 +116,44 @@ This service can be called in several ways:
|
|
105
116
|
|
106
117
|
```ruby
|
107
118
|
# Execute synchronously/in the foreground
|
119
|
+
|
108
120
|
Services::Users::Delete.call User.find(1) # with a user object
|
109
|
-
Services::Users::Delete.call User.where(id: [1, 2, 3]) # with
|
121
|
+
Services::Users::Delete.call User.where(id: [1, 2, 3]) # with a ActiveRecord::Relation returning user objects
|
122
|
+
Services::Users::Delete.call [user1, user2, user3] # with an array of user objects
|
110
123
|
Services::Users::Delete.call 1 # with a user ID
|
111
|
-
Services::Users::Delete.call [1, 2, 3] # with
|
124
|
+
Services::Users::Delete.call [1, 2, 3] # with an array of user IDs
|
112
125
|
|
113
126
|
# Execute asynchronously/in the background
|
127
|
+
|
114
128
|
Services::Users::Delete.perform_async 1 # with a user ID
|
115
129
|
Services::Users::Delete.perform_async [1, 2, 3] # with multiple user IDs
|
116
130
|
```
|
117
131
|
|
118
|
-
As you can see, you cannot use objects when calling a service asynchronously since the arguments are serialized to Redis.
|
132
|
+
As you can see, you cannot use objects or a ActiveRecord::Relation as parameters when calling a service asynchronously since the arguments are serialized to Redis. This might change once Services works with [ActiveJob](https://github.com/rails/rails/tree/master/activejob) and [GlobalID](https://github.com/rails/globalid/).
|
119
133
|
|
120
|
-
The helper `find_objects` is used to
|
134
|
+
The helper `find_objects` is used to allow the `ids_or_objects` parameter to be a object, object ID, array or ActiveRecord::Relation, and make sure you we dealing with an array of objects from that point on.
|
121
135
|
|
122
136
|
It's good practice to always return the objects a service has been operating on at the end of the service.
|
123
137
|
|
124
|
-
|
138
|
+
### Services::Query
|
139
|
+
|
140
|
+
`Services::Query` on the other hand should be the base class for all query objects.
|
141
|
+
|
142
|
+
Here is an example that is used to find users:
|
125
143
|
|
126
144
|
```ruby
|
127
145
|
module Services
|
128
146
|
module Users
|
129
147
|
class Find < Services::Query
|
148
|
+
convert_condition_objects_to_ids :post
|
149
|
+
|
130
150
|
private def process(scope, conditions)
|
131
151
|
conditions.each do |k, v|
|
132
152
|
case k
|
133
153
|
when :email, :name
|
134
154
|
scope = scope.where(k => v)
|
135
|
-
when :
|
136
|
-
scope = scope.joins(:
|
137
|
-
when :product_category_id
|
138
|
-
scope = scope.joins(:product_categories).where("#{ProductCategory.table_name}.id" => v)
|
155
|
+
when :post_id
|
156
|
+
scope = scope.joins(:posts).where("#{Post.table_name}.id" => v)
|
139
157
|
else
|
140
158
|
raise ArgumentError, "Unexpected condition: #{k}"
|
141
159
|
end
|
@@ -147,25 +165,49 @@ module Services
|
|
147
165
|
end
|
148
166
|
```
|
149
167
|
|
150
|
-
|
168
|
+
A query object that inherits from `Services::Query` always receives two parameters: an array of IDs and a hash of conditions. It always returns an array, even if none or only one object is found.
|
151
169
|
|
152
|
-
|
170
|
+
When you write your query objects, the only method you have to write is `process` (preferably make it private). This method does the actual querying for all non-standard parameters (more about standard vs. non-standard parameters below).
|
171
|
+
|
172
|
+
This is how `Services::Users::Find` can be called:
|
173
|
+
|
174
|
+
```ruby
|
175
|
+
Services::Users::Find.call [] # find all users, neither filtered by IDs nor by conditions
|
176
|
+
Services::Users::Find.call [1, 2, 3] # find users with ID 1, 2 or 3
|
177
|
+
Services::Users::Find.call 1 # find users with ID 1 (careful: returns an array containing this one user, if found, otherwise an empty array)
|
178
|
+
Services::Users::Find.call [], email: 'foo@bar.com' # find users with this email address
|
179
|
+
Services::Users::Find.call [1, 2], post: Post.find(1) # find users with ID 1 or 2 and having the post with ID 1
|
180
|
+
Services::Users::Find.call [1, 2], post: [Post.find(1)] # same as above
|
181
|
+
Services::Users::Find.call [1, 2], post: 1 # same as above
|
182
|
+
```
|
153
183
|
|
154
184
|
Check out [the source of `Services::Query`](lib/services/query.rb) to understand what it does in more detail.
|
155
185
|
|
186
|
+
#### Standard vs. non-standard parameters
|
187
|
+
|
188
|
+
to be described...
|
189
|
+
|
190
|
+
#### convert_condition_objects_to_ids
|
191
|
+
|
192
|
+
As with service objects, you want to be able to pass objects or IDs as conditions to query objects as well, and be sure that they behave the same way. This is what `convert_condition_objects_to_ids :post` does in the previous example: it tells the service object to convert the `post` condition, if present, to `post_id`.
|
193
|
+
|
194
|
+
For example, at some point in your app you have an array of posts and need to find the users that created these posts. `Services::Users::Find.call([], post: posts)` will find them for you. If you have a post ID on the other hand, simply use `Services::Users::Find.call([], post: post_id)`, or if you have a single post, use `Services::Users::Find.call([], post: post)`. Each of these calls will return an array of users, as you would expect.
|
195
|
+
|
196
|
+
`Services::Query` takes an array of IDs and a hash of conditions as parameters. It then extracts some special conditions (:order, :limit, :page, :per_page) that are handled separately and passes a `ActiveRecord::Relation` and the remaining conditions to the `process` method that the inheriting class must define. This method should handle all the conditions, extend the scope and return it.
|
197
|
+
|
156
198
|
### Helpers
|
157
199
|
|
158
|
-
Your services inherit from `Services::Base` which makes several helper methods available:
|
200
|
+
Your services inherit from `Services::Base` which makes several helper methods available to them:
|
159
201
|
|
160
202
|
* `Rails.application.routes.url_helpers` is included so you use all Rails URL helpers.
|
161
203
|
* `find_objects` and `find_object` let you automatically find object or a single object from an array of objects or object IDs, or a single object or object ID. The only difference is that `find_object` returns a single object whereas `find_objects` always returns an array.
|
162
204
|
* `object_class` tries to figure out the class the service operates on. If you follow the service naming conventions and you have a service `Services::Products::Find`, `object_class` will return `Product`. Don't call it if you have a service like `Services::DoStuff` or it will raise an exception.
|
163
205
|
|
164
|
-
Your services also automatically get a custom `Error` class, so you can `raise Error, 'Uh-oh, something has gone wrong!'` and a `Services::MyService::Error` will be raised.
|
206
|
+
Your services also automatically get a custom `Error` class, so you can `raise Error, 'Uh-oh, something has gone wrong!'` in `Services::MyService` and a `Services::MyService::Error` will be raised.
|
165
207
|
|
166
208
|
### Logging
|
167
209
|
|
168
|
-
You can choose between logging to Redis or to a file.
|
210
|
+
You can choose between logging to Redis or to a file, or turn logging off. By default logging is turned off.
|
169
211
|
|
170
212
|
#### Redis
|
171
213
|
|
data/lib/services.rb
CHANGED
@@ -6,11 +6,16 @@ module Services
|
|
6
6
|
include GemConfig::Base
|
7
7
|
|
8
8
|
BackgroundProcessorNotFound = Class.new(StandardError)
|
9
|
+
RedisNotFound = Class.new(StandardError)
|
9
10
|
|
10
11
|
with_configuration do
|
11
12
|
has :logger, default: Services::Logger::Null.new
|
12
13
|
has :redis
|
13
14
|
end
|
15
|
+
|
16
|
+
def self.redis
|
17
|
+
@redis ||= self.configuration.redis || (defined?(Redis.current) && Redis.current) or fail RedisNotFound, 'Redis not configured.'
|
18
|
+
end
|
14
19
|
end
|
15
20
|
|
16
21
|
require_relative 'services/version'
|
@@ -27,7 +27,7 @@ module Services
|
|
27
27
|
@_uniqueness_args = args.empty? ? @_service_args : args
|
28
28
|
new_uniqueness_key = uniqueness_key(@_uniqueness_args)
|
29
29
|
raise "A uniqueness key with args #{@_uniqueness_args.inspect} already exists." if @_uniqueness_keys && @_uniqueness_keys.include?(new_uniqueness_key)
|
30
|
-
if @_similar_service_id = Services.
|
30
|
+
if @_similar_service_id = Services.redis.get(new_uniqueness_key)
|
31
31
|
if on_error.to_sym == :ignore
|
32
32
|
return false
|
33
33
|
else
|
@@ -37,7 +37,7 @@ module Services
|
|
37
37
|
else
|
38
38
|
@_uniqueness_keys ||= []
|
39
39
|
@_uniqueness_keys << new_uniqueness_key
|
40
|
-
Services.
|
40
|
+
Services.redis.setex new_uniqueness_key, ONE_DAY, @id
|
41
41
|
true
|
42
42
|
end
|
43
43
|
end
|
@@ -62,8 +62,8 @@ module Services
|
|
62
62
|
raise "Unexpected on_error: #{@_on_error}"
|
63
63
|
end
|
64
64
|
ensure
|
65
|
-
Services.
|
66
|
-
Services.
|
65
|
+
Services.redis.del @_uniqueness_keys unless Array(@_uniqueness_keys).empty?
|
66
|
+
Services.redis.del error_count_key
|
67
67
|
end
|
68
68
|
|
69
69
|
private
|
@@ -99,11 +99,11 @@ module Services
|
|
99
99
|
end
|
100
100
|
|
101
101
|
def error_count
|
102
|
-
(Services.
|
102
|
+
(Services.redis.get(error_count_key) || 0).to_i
|
103
103
|
end
|
104
104
|
|
105
105
|
def increase_error_count
|
106
|
-
Services.
|
106
|
+
Services.redis.setex error_count_key, retry_delay + ONE_DAY, error_count + 1
|
107
107
|
end
|
108
108
|
|
109
109
|
def uniqueness_key(args)
|
data/lib/services/version.rb
CHANGED
data/spec/services/base_spec.rb
CHANGED
@@ -45,7 +45,7 @@ describe Services::Base do
|
|
45
45
|
context 'when passing in something else than a single object or ID' do
|
46
46
|
it 'raises an error' do
|
47
47
|
[%w(foo bar), nil, Object.new].each do |object|
|
48
|
-
expect { Services::Models::FindObjectTest.call(object) }.to raise_error
|
48
|
+
expect { Services::Models::FindObjectTest.call(object) }.to raise_error(Services::Models::FindObjectTest::Error)
|
49
49
|
end
|
50
50
|
end
|
51
51
|
end
|
@@ -91,7 +91,7 @@ describe Services::Base do
|
|
91
91
|
context 'when passing in something else than a single object or ID' do
|
92
92
|
it 'raises an error' do
|
93
93
|
[%w(foo bar), nil, Object.new].each do |object|
|
94
|
-
expect { Services::Models::FindIdTest.call(object) }.to raise_error
|
94
|
+
expect { Services::Models::FindIdTest.call(object) }.to raise_error(Services::Models::FindIdTest::Error)
|
95
95
|
end
|
96
96
|
end
|
97
97
|
end
|
@@ -77,7 +77,7 @@ shared_examples 'checking the uniqueness properly' do
|
|
77
77
|
|
78
78
|
# Check that all Redis keys are deleted
|
79
79
|
key_pattern = "#{described_class::KEY_PREFIX}*"
|
80
|
-
expect(Services.
|
80
|
+
expect(Services.redis.keys(key_pattern)).to be_empty
|
81
81
|
end
|
82
82
|
end
|
83
83
|
|
data/spec/spec_helper.rb
CHANGED
@@ -17,22 +17,20 @@ SIDEKIQ_PIDFILE = SUPPORT_DIR.join('sidekiq.pid')
|
|
17
17
|
WAIT = 0.5
|
18
18
|
START_TIMEOUT = 5
|
19
19
|
SIDEKIQ_TIMEOUT = 20
|
20
|
-
|
20
|
+
REDIS_URL = 'redis://localhost:6379/0'
|
21
21
|
|
22
22
|
%w(shared helpers test_services).each do |file|
|
23
23
|
require SUPPORT_DIR.join(file)
|
24
24
|
end
|
25
25
|
|
26
|
-
|
27
|
-
config.redis = Redis.new
|
28
|
-
end
|
26
|
+
Redis.current = Redis.new(url: REDIS_URL)
|
29
27
|
|
30
28
|
Sidekiq.configure_client do |config|
|
31
|
-
config.redis = {
|
29
|
+
config.redis = { url: REDIS_URL, namespace: 'sidekiq', size: 1 }
|
32
30
|
end
|
33
31
|
|
34
32
|
Sidekiq.configure_server do |config|
|
35
|
-
config.redis = {
|
33
|
+
config.redis = { url: REDIS_URL, namespace: 'sidekiq' }
|
36
34
|
end
|
37
35
|
|
38
36
|
RSpec.configure do |config|
|
@@ -27,7 +27,9 @@ module Services
|
|
27
27
|
class FindRaiseConditions < Services::Query
|
28
28
|
convert_condition_objects_to_ids :comment
|
29
29
|
|
30
|
-
private
|
30
|
+
private
|
31
|
+
|
32
|
+
def process(scope, conditions)
|
31
33
|
raise conditions.to_json
|
32
34
|
end
|
33
35
|
end
|
@@ -39,7 +41,9 @@ module Services
|
|
39
41
|
class Find < Services::Query
|
40
42
|
convert_condition_objects_to_ids :comment
|
41
43
|
|
42
|
-
private
|
44
|
+
private
|
45
|
+
|
46
|
+
def process(scope, conditions)
|
43
47
|
conditions.each do |k, v|
|
44
48
|
case k
|
45
49
|
when :title, :body
|
@@ -61,7 +65,9 @@ module Services
|
|
61
65
|
class Find < Services::Query
|
62
66
|
convert_condition_objects_to_ids :post
|
63
67
|
|
64
|
-
private
|
68
|
+
private
|
69
|
+
|
70
|
+
def process(scope, conditions)
|
65
71
|
conditions.each do |k, v|
|
66
72
|
case k
|
67
73
|
when :body, :post_id
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: services
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.1.
|
4
|
+
version: 4.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Manuel Meurer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-02-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -214,7 +214,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
214
214
|
version: '0'
|
215
215
|
requirements: []
|
216
216
|
rubyforge_project:
|
217
|
-
rubygems_version: 2.
|
217
|
+
rubygems_version: 2.5.1
|
218
218
|
signing_key:
|
219
219
|
specification_version: 4
|
220
220
|
summary: A nifty service layer for your Rails app
|