services 2.2.6 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1400e6ff9c2b46562e08881c6d094a0bb5de1459
4
- data.tar.gz: 5e7b0018546aadd2b51d8e319cc2c5a551d7c893
3
+ metadata.gz: d53cbcc74506968392685a47758d817de8567d05
4
+ data.tar.gz: 40e349518171bac33c11e2ff5ade10e823236c21
5
5
  SHA512:
6
- metadata.gz: e0bd521415d59a379fb9f3dce599d18631df2e6255239d559d12b52d6e92d235bac4f10234e959257ca44ab0c235c7e4f0ffc565682555247c249167487dbffe
7
- data.tar.gz: d9af93a2ce8ad3c855bde9e30b9681a2ec0a877758acf5297c0828bddf95524d7926f23a699e2179b18dfa7b2e0e55deaa25922d9c51edc652165205994f5ad9
6
+ metadata.gz: e2c5f4c9db7cac2dea8ffc1ddfd202cd35a67fea3e5f21185a303a862cc30013ba962a8659fa2850a964497268b1c4a355b339b05243c60153b4ec0f298d6de0
7
+ data.tar.gz: d822b34fe0db413a3b310bd4560cc7d14bd0d6f6da92693cc2cb007e2335103fa7754be76efd9d26eebd09c7fa94a40aa3d3183087890b1bf2a5bb4134bbfa55
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## 3.0.0
2
+
3
+ * Rename `BaseFinder` to `Query`
4
+ * `Query` doesn't inherit from `Base` anymore
5
+ * Only use SQL subquery in `Query` if a JOIN is used
6
+
1
7
  ## 2.2.4
2
8
 
3
9
  * Increase TTL for Redis keys for uniqueness and error count to one day
data/README.md CHANGED
@@ -33,7 +33,7 @@ To process services in the background, Services uses [Sidekiq](https://github.co
33
33
 
34
34
  #### Postgres
35
35
 
36
- The SQL that `Services::BaseFinder` (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::BaseFinder` or, even better, submit a [pull request](https://github.com/krautcomputing/services/issues) that fixes it to work with your database!
36
+ 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!
37
37
 
38
38
  ### Basic principles
39
39
 
@@ -54,7 +54,7 @@ Apart from these basic principles, you can implement the actual logic in a servi
54
54
 
55
55
  Follow these conventions when using Services in your Rails app:
56
56
 
57
- * services inherit from `Services::Base` (or `Services::BaseFinder`)
57
+ * services inherit from `Services::Base` (or `Services::Query`)
58
58
  * services are located in `app/services/`
59
59
  * services are namespaced with the model they operate on and their names are verbs, 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::CleanOldUsers`, `Services::Maintenance::SendDailySummary`, etc.)
60
60
  * 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.
@@ -121,12 +121,12 @@ As you can see, the helper `find_objects` is used to make sure you are dealing w
121
121
 
122
122
  It's good practice to always return the objects a service has been operating on at the end of the service.
123
123
 
124
- Another example, this time using `Services::BaseFinder`:
124
+ Another example, this time using `Services::Query`:
125
125
 
126
126
  ```ruby
127
127
  module Services
128
128
  module Users
129
- class Find < Services::BaseFinder
129
+ class Find < Services::Query
130
130
  private def process(scope, conditions)
131
131
  conditions.each do |k, v|
132
132
  case k
@@ -147,11 +147,11 @@ module Services
147
147
  end
148
148
  ```
149
149
 
150
- Since you will create services to find objects for pretty much every model you have and they all look very similar, i.e. process the find conditions and return a `ActiveRecord::Relation`, you can let those services inherit from `Services::BaseFinder` to remove some of the boilerplate.
150
+ Since you will create services to find objects for pretty much every model you have and they all look very similar, i.e. process the find conditions and return a `ActiveRecord::Relation`, you can let those services inherit from `Services::Query` to remove some of the boilerplate.
151
151
 
152
- `Services::BaseFinder` inherits from `Services::Base` and 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.
152
+ `Services::Query` inherits from `Services::Base` and 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.
153
153
 
154
- Check out [the source of `Services::BaseFinder`](lib/services/base_finder.rb) to understand what it does in more detail.
154
+ Check out [the source of `Services::Query`](lib/services/base_finder.rb) to understand what it does in more detail.
155
155
 
156
156
  ### Helpers
157
157
 
data/lib/services.rb CHANGED
@@ -21,6 +21,8 @@ rescue Services::BackgroundProcessorNotFound
21
21
  end
22
22
  require_relative 'services/modules/call_logger'
23
23
  require_relative 'services/modules/exception_wrapper'
24
+ require_relative 'services/modules/object_class'
24
25
  require_relative 'services/modules/uniqueness_checker'
25
26
  require_relative 'services/base'
27
+ require_relative 'services/query'
26
28
  require_relative 'services/railtie' if defined?(Rails)
data/lib/services/base.rb CHANGED
@@ -4,6 +4,8 @@ require 'digest'
4
4
 
5
5
  module Services
6
6
  class Base
7
+ include ObjectClass
8
+
7
9
  class << self
8
10
  def inherited(subclass)
9
11
  subclass.const_set :Error, Class.new(StandardError)
@@ -65,12 +67,6 @@ module Services
65
67
  end
66
68
  end
67
69
 
68
- def object_class
69
- self.class.to_s[/Services::([^:]+)/, 1].singularize.constantize
70
- rescue
71
- raise "Could not determine service class from #{self.class}"
72
- end
73
-
74
70
  def controller
75
71
  @controller ||= begin
76
72
  raise 'Please configure host.' if Services.configuration.host.nil?
@@ -0,0 +1,9 @@
1
+ module Services
2
+ module ObjectClass
3
+ private def object_class
4
+ self.class.to_s[/\AServices::([^:]+)/, 1].singularize.constantize
5
+ rescue
6
+ raise "Could not determine service class from #{self.class}."
7
+ end
8
+ end
9
+ end
@@ -1,6 +1,10 @@
1
1
  module Services
2
- class BaseFinder < Services::Base
3
- disable_call_logging
2
+ class Query
3
+ include ObjectClass
4
+
5
+ class << self
6
+ delegate :call, to: :new
7
+ end
4
8
 
5
9
  def call(ids = [], conditions = {})
6
10
  ids, conditions = Array(ids), conditions.symbolize_keys
@@ -14,7 +18,10 @@ module Services
14
18
 
15
19
  unless conditions.empty?
16
20
  scope = process(scope, conditions)
17
- scope = object_class.where(id: scope.select("DISTINCT #{object_table_id}"))
21
+ # If a JOIN is involved, use a subquery to make sure we're getting DISTINCT records.
22
+ if scope.to_sql =~ / join /i
23
+ scope = object_class.where(id: scope.select("DISTINCT #{object_table_id}"))
24
+ end
18
25
  end
19
26
 
20
27
  special_conditions.each do |k, v|
@@ -1,9 +1,9 @@
1
1
  module Services
2
2
  class Railtie < Rails::Railtie
3
- # Require the base finder here since it relies
4
- # on Rails.application to be present
5
- initializer 'services.load_base_finder' do
6
- require 'services/base_finder'
3
+ # Require `Services::Query` here since it relies
4
+ # on Rails.application to be present.
5
+ initializer 'services.load_services_query' do
6
+ require 'services/query'
7
7
  end
8
8
  end
9
9
  end
@@ -1,3 +1,3 @@
1
1
  module Services
2
- VERSION = '2.2.6'
2
+ VERSION = '3.0.0'
3
3
  end
@@ -1,12 +1,12 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Services::BaseFinder do
3
+ describe Services::Query do
4
4
  include_context 'capture logs'
5
5
 
6
6
  let(:base_find) { Services::Models::BaseFind }
7
7
 
8
8
  it 'has call logging disabled by default' do
9
- pending 'Rails has to be loaded to call BaseFinder'
9
+ pending 'Rails has to be loaded to call Query'
10
10
  expect(base_find.call_logging_disabled).to eq(true)
11
11
  expect { base_find.call }.to_not change { logs }
12
12
  end
@@ -1,4 +1,4 @@
1
- require 'services/base_finder'
1
+ require 'services/query'
2
2
 
3
3
  class Model
4
4
  class << self
@@ -42,7 +42,7 @@ end
42
42
 
43
43
  module Services
44
44
  module Models
45
- class BaseFind < Services::BaseFinder
45
+ class Query < Services::Query
46
46
  private
47
47
 
48
48
  def process(scope, conditions)
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: 2.2.6
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Manuel Meurer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-12-19 00:00:00.000000000 Z
11
+ date: 2014-12-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -153,21 +153,22 @@ files:
153
153
  - lib/services.rb
154
154
  - lib/services/asyncable.rb
155
155
  - lib/services/base.rb
156
- - lib/services/base_finder.rb
157
156
  - lib/services/logger/file.rb
158
157
  - lib/services/logger/redis.rb
159
158
  - lib/services/modules/call_logger.rb
160
159
  - lib/services/modules/exception_wrapper.rb
160
+ - lib/services/modules/object_class.rb
161
161
  - lib/services/modules/uniqueness_checker.rb
162
+ - lib/services/query.rb
162
163
  - lib/services/railtie.rb
163
164
  - lib/services/version.rb
164
165
  - services.gemspec
165
- - spec/services/base_finder_spec.rb
166
166
  - spec/services/base_spec.rb
167
167
  - spec/services/logger/redis_spec.rb
168
168
  - spec/services/modules/call_logger_spec.rb
169
169
  - spec/services/modules/exception_wrapper_spec.rb
170
170
  - spec/services/modules/uniqueness_checker_spec.rb
171
+ - spec/services/query_spec.rb
171
172
  - spec/spec_helper.rb
172
173
  - spec/support/call_proxy.rb
173
174
  - spec/support/helpers.rb
@@ -201,12 +202,12 @@ signing_key:
201
202
  specification_version: 4
202
203
  summary: A nifty service layer for your Rails app
203
204
  test_files:
204
- - spec/services/base_finder_spec.rb
205
205
  - spec/services/base_spec.rb
206
206
  - spec/services/logger/redis_spec.rb
207
207
  - spec/services/modules/call_logger_spec.rb
208
208
  - spec/services/modules/exception_wrapper_spec.rb
209
209
  - spec/services/modules/uniqueness_checker_spec.rb
210
+ - spec/services/query_spec.rb
210
211
  - spec/spec_helper.rb
211
212
  - spec/support/call_proxy.rb
212
213
  - spec/support/helpers.rb