edge_rider 1.1.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,7 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  # Runtime dependencies
4
- gem 'activerecord', '~>6.0.0.rc1'
4
+ gem 'activerecord', '~>6.1.3'
5
5
  gem 'pg'
6
6
 
7
7
  # Development dependencies
@@ -9,7 +9,7 @@ gem 'rake'
9
9
  gem 'database_cleaner'
10
10
  gem 'has_defaults' # used by test models
11
11
  gem 'rspec'
12
- gem 'gemika'
12
+ gem 'gemika', '>=0.5.0'
13
13
  gem 'pry-byebug'
14
14
 
15
15
  # Gem under test
@@ -0,0 +1,78 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ edge_rider (2.0.0)
5
+ activerecord (>= 3.2)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ activemodel (6.1.3)
11
+ activesupport (= 6.1.3)
12
+ activerecord (6.1.3)
13
+ activemodel (= 6.1.3)
14
+ activesupport (= 6.1.3)
15
+ activesupport (6.1.3)
16
+ concurrent-ruby (~> 1.0, >= 1.0.2)
17
+ i18n (>= 1.6, < 2)
18
+ minitest (>= 5.1)
19
+ tzinfo (~> 2.0)
20
+ zeitwerk (~> 2.3)
21
+ byebug (11.1.3)
22
+ coderay (1.1.3)
23
+ concurrent-ruby (1.1.8)
24
+ database_cleaner (2.0.1)
25
+ database_cleaner-active_record (~> 2.0.0)
26
+ database_cleaner-active_record (2.0.0)
27
+ activerecord (>= 5.a)
28
+ database_cleaner-core (~> 2.0.0)
29
+ database_cleaner-core (2.0.1)
30
+ diff-lcs (1.4.4)
31
+ gemika (0.5.0)
32
+ has_defaults (0.4.4)
33
+ activerecord
34
+ i18n (1.8.9)
35
+ concurrent-ruby (~> 1.0)
36
+ method_source (1.0.0)
37
+ minitest (5.14.4)
38
+ pg (1.2.3)
39
+ pry (0.13.1)
40
+ coderay (~> 1.1)
41
+ method_source (~> 1.0)
42
+ pry-byebug (3.9.0)
43
+ byebug (~> 11.0)
44
+ pry (~> 0.13.0)
45
+ rake (13.0.3)
46
+ rspec (3.10.0)
47
+ rspec-core (~> 3.10.0)
48
+ rspec-expectations (~> 3.10.0)
49
+ rspec-mocks (~> 3.10.0)
50
+ rspec-core (3.10.1)
51
+ rspec-support (~> 3.10.0)
52
+ rspec-expectations (3.10.1)
53
+ diff-lcs (>= 1.2.0, < 2.0)
54
+ rspec-support (~> 3.10.0)
55
+ rspec-mocks (3.10.2)
56
+ diff-lcs (>= 1.2.0, < 2.0)
57
+ rspec-support (~> 3.10.0)
58
+ rspec-support (3.10.2)
59
+ tzinfo (2.0.4)
60
+ concurrent-ruby (~> 1.0)
61
+ zeitwerk (2.4.2)
62
+
63
+ PLATFORMS
64
+ ruby
65
+
66
+ DEPENDENCIES
67
+ activerecord (~> 6.1.3)
68
+ database_cleaner
69
+ edge_rider!
70
+ gemika (>= 0.5.0)
71
+ has_defaults
72
+ pg
73
+ pry-byebug
74
+ rake
75
+ rspec
76
+
77
+ BUNDLED WITH
78
+ 2.2.26
data/Gemfile.lock ADDED
@@ -0,0 +1 @@
1
+ Gemfile.6.1.pg.lock
data/README.md CHANGED
@@ -1,8 +1,6 @@
1
- Edge Rider [![Build Status](https://secure.travis-ci.org/makandra/edge_rider.png?branch=master)](https://travis-ci.org/makandra/edge_rider)
2
- ====================================
1
+ # Edge Rider [![Tests](https://github.com/makandra/edge_rider/workflows/Tests/badge.svg)](https://github.com/makandra/edge_rider/actions)
3
2
 
4
- Power tools for ActiveRecord relations (scopes)
5
- -------------------------------------------------
3
+ ## Power tools for ActiveRecord relations (scopes)
6
4
 
7
5
  In ActiveRecord, relations (or scopes) allow you to construct complex queries piece-by-piece
8
6
  and then trigger a query or update at a precisely defined moment. If you write any kind
@@ -14,9 +12,7 @@ Edge Rider was created with two intents:
14
12
  2. Provide a stable API for working with relations across multiple versions of Rails (since
15
13
  Rails has a tradition of breaking details of its relation API every other release).
16
14
 
17
-
18
- Usage
19
- -----
15
+ ## Usage
20
16
 
21
17
  ### Traversing a relation along an association
22
18
 
@@ -25,20 +21,26 @@ returns a new relation by "pivoting" around a named association.
25
21
 
26
22
  Say we have a `Post` model and each `Post` belongs to an author:
27
23
 
28
- class Post < ActiveRecord::Base
29
- belongs_to :author
30
- end
31
-
24
+ ```ruby
25
+ class Post < ActiveRecord::Base
26
+ belongs_to :author
27
+ end
28
+ ```
29
+
32
30
  To turn a relation of posts into a relation of its authors:
33
31
 
34
- posts = Post.where(archived: false)
35
- authors = posts.traverse_association(:author)
36
-
32
+ ```ruby
33
+ posts = Post.where(archived: false)
34
+ authors = posts.traverse_association(:author)
35
+ ```
36
+
37
37
  You can traverse multiple associations in a single call.
38
38
  E.g. to turn a relation of posts into a relation of all posts of their authors:
39
39
 
40
- posts = Post.where(archived: false)
41
- posts_by_same_authors = posts.traverse_association(:author, :posts)
40
+ ```ruby
41
+ posts = Post.where(archived: false)
42
+ posts_by_same_authors = posts.traverse_association(:author, :posts)
43
+ ```
42
44
 
43
45
  *Implementation note:* The traversal is achieved internally by collecting all foreign keys in the current relation
44
46
  and return a new relation with an `IN(...)` query (which is very efficient even for many thousand keys).
@@ -56,8 +58,10 @@ its ID.
56
58
  Edge Rider has a better way. Your relations gain a method `#collect_ids` that will
57
59
  fetch all IDs in a single query without instantiating a single ActiveRecord object:
58
60
 
59
- posts = Post.where(archived: false)
60
- post_ids = posts.collect_ids
61
+ ```ruby
62
+ posts = Post.where(archived: false)
63
+ post_ids = posts.collect_ids
64
+ ```
61
65
 
62
66
  *Implementation note:* `#collect_ids` delegates to [`#pluck`](https://apidock.com/rails/ActiveRecord/Calculations/pluck),
63
67
  which can be used for the same purpose.
@@ -68,33 +72,39 @@ which can be used for the same purpose.
68
72
  When writing a method that filters by record IDs, you can make it more useful by accepting
69
73
  any kind of argument that can be turned into a list of IDs:
70
74
 
71
- Post.by_author(1)
72
- Post.by_author([1, 2, 3])
73
- Post.by_author(Author.find(1))
74
- Post.by_author([Author.find(1), Author.find(2)])
75
- Post.by_author(Author.active)
75
+ ```ruby
76
+ Post.by_author(1)
77
+ Post.by_author([1, 2, 3])
78
+ Post.by_author(Author.find(1))
79
+ Post.by_author([Author.find(1), Author.find(2)])
80
+ Post.by_author(Author.active)
81
+ ```
76
82
 
77
83
  For this use case Edge Rider defines `#collect_ids` on many different types:
78
84
 
79
- Post.where(id: [1, 2]).collect_ids # => [1, 2]
80
- [Post.find(1), Post.find(2)].collect_ids # => [1, 2]
81
- Post.find(1).collect_ids # => [1]
82
- [1, 2, 3].collect_ids # => [1, 2, 3]
83
- 1.collect_ids # => [1]
85
+ ```ruby
86
+ Post.where(id: [1, 2]).collect_ids # => [1, 2]
87
+ [Post.find(1), Post.find(2)].collect_ids # => [1, 2]
88
+ Post.find(1).collect_ids # => [1]
89
+ [1, 2, 3].collect_ids # => [1, 2, 3]
90
+ 1.collect_ids # => [1]
91
+ ```
84
92
 
85
93
  You can now write `Post.by_author` from the example above without a single `if` or `case`:
86
94
 
87
- class Post < ActiveRecord::Base
88
-
89
- belongs_to :author
95
+ ```ruby
96
+ class Post < ActiveRecord::Base
97
+
98
+ belongs_to :author
99
+
100
+ def self.for_author(author_or_authors)
101
+ where(author_id: author_or_authors.collect_ids)
102
+ end
103
+
104
+ end
105
+ ```
90
106
 
91
- def self.for_author(author_or_authors)
92
- where(author_id: author_or_authors.collect_ids)
93
- end
94
107
 
95
- end
96
-
97
-
98
108
  ### Efficiently collect all values in a relation's column
99
109
 
100
110
  You often want to ask a relation for an array of all values ofin a given column.
@@ -106,8 +116,10 @@ its column value.
106
116
  Edge Rider has a better way. Your relations gain a method `#collect_column` that will
107
117
  fetch all column values in a single query without instantiating a single ActiveRecord object:
108
118
 
109
- posts = Post.where(archived: false)
110
- subjects = posts.collect_column(:subject)
119
+ ```ruby
120
+ posts = Post.where(archived: false)
121
+ subjects = posts.collect_column(:subject)
122
+ ```
111
123
 
112
124
  *Implementation note:* `#collect_column` delegates to [`#pluck`](https://apidock.com/rails/ActiveRecord/Calculations/pluck),
113
125
  which can be used for the same effect.
@@ -116,8 +128,10 @@ which can be used for the same effect.
116
128
 
117
129
  If you only care about *unique* values, use the `distinct: true` option:
118
130
 
119
- posts = Post.where(archived: false)
120
- distinct_subjects = posts.collect_column(:subject, distinct: true)
131
+ ```ruby
132
+ posts = Post.where(archived: false)
133
+ distinct_subjects = posts.collect_column(:subject, distinct: true)
134
+ ```
121
135
 
122
136
  With this options duplicates are discarded by the database before making their way into Ruby.
123
137
 
@@ -136,15 +150,21 @@ mashes together strings that mostly happen to look like a MySQL query in the end
136
150
 
137
151
  Edge Rider gives your relations a new method `#to_id_query`:
138
152
 
139
- Site.joins(user).where(:users: { name: 'Bruce' }).to_id_query
153
+ ```ruby
154
+ Site.joins(user).where(:users: { name: 'Bruce' }).to_id_query
155
+ ```
140
156
 
141
157
  `#to_id_query` will immediately run an SQL query where it collects all the IDs that match your relation:
142
158
 
143
- SELECT sites.id FROM sites INNER JOIN users WHERE sites.user_id = sites.id AND users.name = 'Bruce'
159
+ ```sql
160
+ SELECT sites.id FROM sites INNER JOIN users WHERE sites.user_id = sites.id AND users.name = 'Bruce'
161
+ ```
144
162
 
145
163
  It now uses these IDs to return a new relation that has **no joins** and a single condition on the `id` column:
146
164
 
147
- SELECT * FROM sites WHERE sites.user_id IN (3, 17, 103)
165
+ ```sql
166
+ SELECT * FROM sites WHERE sites.user_id IN (3, 17, 103)
167
+ ```
148
168
 
149
169
 
150
170
  ### Preload associations for loaded ActiveRecords
@@ -153,23 +173,26 @@ Sometimes you want to fetch associations for records that you already instantiat
153
173
 
154
174
  Edge Rider gives your model classes and instances a method `preload_associations`. The method can be used to preload associations for loaded objects like this:
155
175
 
156
- @user = User.find(params[:id])
157
- User.preload_associations [@user], { threads: { posts: :author }, messages: :sender }
158
- # or
159
- user.preload_associations { threads: { posts: :author }, messages: :sender }
176
+ ```ruby
177
+ @user = User.find(params[:id])
178
+ User.preload_associations [@user], { threads: { posts: :author }, messages: :sender }
179
+ # or
180
+ user.preload_associations { threads: { posts: :author }, messages: :sender }
181
+ ```
160
182
 
161
183
  *Implementation note*: Rails 3.0 already has a method [`.preload_associations`](https://apidock.com/rails/ActiveRecord/AssociationPreload/ClassMethods/preload_associations)
162
184
  which Edge Rider merely makes public. Edge Rider ports this method forward to Rails 3.1+.
163
185
 
164
186
 
165
-
166
187
  ### Retrieve the class a relation is based on
167
188
 
168
189
  Edge Rider gives your relations a method `#origin_class` that returns the class the relation is based on.
169
190
  This is useful e.g. to perform unscoped record look-up.
170
191
 
171
- Post.recent.origin_class
172
- # => Post
192
+ ```ruby
193
+ Post.recent.origin_class
194
+ # => Post
195
+ ```
173
196
 
174
197
  Note that `#origin_class` it roughly equivalent to the blockless form of [`unscoped`](https://apidock.com/rails/ActiveRecord/Scoping/Default/ClassMethods/unscoped) from Rails 3.2+,
175
198
  but it works consistently across all Rails versions.
@@ -182,8 +205,10 @@ Edge Rider ports `Model.scoped` forward to Rails 4+ (taken from
182
205
  enables you to consistently turn models into scopes or narrow down scopes
183
206
  across all versions of Rails.
184
207
 
185
- User.scoped # just calls User.all in Rails 4
186
- User.active.scoped(conditions: { admin: true })
208
+ ```ruby
209
+ User.scoped # just calls User.all in Rails 4
210
+ User.active.scoped(conditions: { admin: true })
211
+ ```
187
212
 
188
213
  *Implementation note*: Rails 3 already have a method
189
214
  [`.scoped`](https://apidock.com/rails/ActiveRecord/Scoping/Named/ClassMethods/scoped) which Edge Rider does not touch. Rails 4 has removed this method and
@@ -196,18 +221,18 @@ slightly different in all versions of Rails (see
196
221
  methods are not modified.
197
222
 
198
223
 
199
- Installation
200
- ------------
224
+ ## Installation
201
225
 
202
226
  In your `Gemfile` say:
203
227
 
204
- gem 'edge_rider'
228
+ ```ruby
229
+ gem 'edge_rider'
230
+ ```
205
231
 
206
232
  Now run `bundle install` and restart your server.
207
233
 
208
234
 
209
- Development
210
- -----------
235
+ ## Development
211
236
 
212
237
  - There are tests in `spec`. We only accept PRs with tests.
213
238
  - We currently develop using the Ruby version in `.ruby-version`. It is required to change the Ruby Version to cover all Rails version or just use Travis CI.
@@ -224,7 +249,6 @@ If you would like to contribute:
224
249
  - Send me a pull request.
225
250
 
226
251
 
227
- Credits
228
- -------
252
+ ## Credits
229
253
 
230
254
  Henning Koch from [makandra](http://makandra.com/)
data/edge_rider.gemspec CHANGED
@@ -1,21 +1,29 @@
1
- $:.push File.expand_path("../lib", __FILE__)
1
+ lib = File.expand_path('lib', __dir__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
2
3
  require "edge_rider/version"
3
4
 
4
- Gem::Specification.new do |s|
5
- s.name = 'edge_rider'
6
- s.version = EdgeRider::VERSION
7
- s.authors = ["Henning Koch"]
8
- s.email = 'henning.koch@makandra.de'
9
- s.homepage = 'https://github.com/makandra/edge_rider'
10
- s.summary = 'Power tools for ActiveRecord relations (scopes)'
11
- s.description = s.summary
12
- s.license = 'MIT'
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'edge_rider'
7
+ spec.version = EdgeRider::VERSION
8
+ spec.required_ruby_version = '>= 2.3.0'
9
+ spec.authors = ['Henning Koch']
10
+ spec.email = ['henning.koch@makandra.de']
13
11
 
14
- s.files = `git ls-files`.split("\n").select { |path| File.exist?(path) && !File.symlink?(path) }
15
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n").select { |path| File.exist?(path) && !File.symlink?(path) }
16
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
- s.require_paths = ["lib"]
12
+ spec.summary = 'Power tools for ActiveRecord relations (scopes)'
13
+ spec.description = spec.summary
14
+ spec.homepage = 'https://github.com/makandra/edge_rider'
15
+ spec.license = 'MIT'
18
16
 
19
- s.add_dependency('activerecord', '>=3.2')
20
- s.required_ruby_version = ">= 2.2"
17
+ # Specify which files should be added to the gem when it is released.
18
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
19
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
20
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
21
+ end
22
+ spec.bindir = 'exe'
23
+ spec.executables = spec.files.grep(%r(^exe/)) { |f| File.basename(f) }
24
+ spec.require_paths = ['lib']
25
+
26
+ spec.add_dependency('activerecord', '>=3.2')
27
+
28
+ # Development dependencies are defined in the Gemfile (therefore no `spec.add_development_dependency` directives)
21
29
  end
@@ -52,7 +52,7 @@ module EdgeRider
52
52
  # but Rails 2 does not have it.
53
53
  other_options = options.slice!(:conditions)
54
54
  scope = lambda { |*args| scoped(options) }
55
- owner.send association, target, scope, other_options
55
+ owner.send association, target, scope, **other_options
56
56
  end
57
57
  end
58
58
 
@@ -1,3 +1,3 @@
1
1
  module EdgeRider
2
- VERSION = '1.1.0'
2
+ VERSION = '2.0.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: edge_rider
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Henning Koch
8
8
  autorequire:
9
- bindir: bin
9
+ bindir: exe
10
10
  cert_chain: []
11
- date: 2019-12-13 00:00:00.000000000 Z
11
+ date: 2021-08-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -25,17 +25,18 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '3.2'
27
27
  description: Power tools for ActiveRecord relations (scopes)
28
- email: henning.koch@makandra.de
28
+ email:
29
+ - henning.koch@makandra.de
29
30
  executables: []
30
31
  extensions: []
31
32
  extra_rdoc_files: []
32
33
  files:
34
+ - ".github/workflows/test.yml"
33
35
  - ".gitignore"
36
+ - ".rspec"
34
37
  - ".ruby-version"
35
- - ".travis.yml"
36
38
  - CHANGELOG.md
37
- - Gemfile.3.2.mysql2
38
- - Gemfile.3.2.mysql2.lock
39
+ - Gemfile
39
40
  - Gemfile.4.2.mysql2
40
41
  - Gemfile.4.2.mysql2.lock
41
42
  - Gemfile.4.2.pg
@@ -44,8 +45,9 @@ files:
44
45
  - Gemfile.5.2.mysql2.lock
45
46
  - Gemfile.5.2.pg
46
47
  - Gemfile.5.2.pg.lock
47
- - Gemfile.6.0.pg
48
- - Gemfile.6.0.pg.lock
48
+ - Gemfile.6.1.pg
49
+ - Gemfile.6.1.pg.lock
50
+ - Gemfile.lock
49
51
  - LICENSE
50
52
  - README.md
51
53
  - Rakefile
@@ -61,19 +63,6 @@ files:
61
63
  - lib/edge_rider/traverse_association.rb
62
64
  - lib/edge_rider/util.rb
63
65
  - lib/edge_rider/version.rb
64
- - spec/edge_rider/collect_column_spec.rb
65
- - spec/edge_rider/collect_ids_spec.rb
66
- - spec/edge_rider/origin_class_spec.rb
67
- - spec/edge_rider/preload_associations_spec.rb
68
- - spec/edge_rider/scoped_spec.rb
69
- - spec/edge_rider/to_id_query_spec.rb
70
- - spec/edge_rider/traverse_association_spec.rb
71
- - spec/edge_rider/util_spec.rb
72
- - spec/spec_helper.rb
73
- - spec/support/database.rb
74
- - spec/support/database.sample.yml
75
- - spec/support/database.travis.yml
76
- - spec/support/models.rb
77
66
  homepage: https://github.com/makandra/edge_rider
78
67
  licenses:
79
68
  - MIT
@@ -86,14 +75,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
86
75
  requirements:
87
76
  - - ">="
88
77
  - !ruby/object:Gem::Version
89
- version: '2.2'
78
+ version: 2.3.0
90
79
  required_rubygems_version: !ruby/object:Gem::Requirement
91
80
  requirements:
92
81
  - - ">="
93
82
  - !ruby/object:Gem::Version
94
83
  version: '0'
95
84
  requirements: []
96
- rubygems_version: 3.0.6
85
+ rubygems_version: 3.2.26
97
86
  signing_key:
98
87
  specification_version: 4
99
88
  summary: Power tools for ActiveRecord relations (scopes)