edge_rider 1.1.0 → 2.0.0

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.
@@ -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)