edge_rider 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. data/.gitignore +10 -0
  2. data/.rvmrc +2 -0
  3. data/.travis.yml +15 -0
  4. data/README.md +41 -0
  5. data/Rakefile +55 -0
  6. data/edge_rider.gemspec +20 -0
  7. data/lib/edge_rider/collect_column.rb +23 -0
  8. data/lib/edge_rider/collect_ids.rb +53 -0
  9. data/lib/edge_rider/development.rb +27 -0
  10. data/lib/edge_rider/to_id_query.rb +12 -0
  11. data/lib/edge_rider/to_sql.rb +13 -0
  12. data/lib/edge_rider/traverse_association.rb +40 -0
  13. data/lib/edge_rider/util.rb +32 -0
  14. data/lib/edge_rider/version.rb +3 -0
  15. data/lib/edge_rider.rb +10 -0
  16. data/spec/rails-2.3/Gemfile +13 -0
  17. data/spec/rails-2.3/Rakefile +11 -0
  18. data/spec/rails-2.3/app_root/config/boot.rb +130 -0
  19. data/spec/rails-2.3/app_root/config/database.yml +6 -0
  20. data/spec/rails-2.3/app_root/config/environment.rb +16 -0
  21. data/spec/rails-2.3/app_root/config/environments/test.rb +0 -0
  22. data/spec/rails-2.3/app_root/config/initializers/fix_missing_source_file.rb +1 -0
  23. data/spec/rails-2.3/app_root/config/preinitializer.rb +22 -0
  24. data/spec/rails-2.3/app_root/config/routes.rb +15 -0
  25. data/spec/rails-2.3/app_root/log/.gitignore +1 -0
  26. data/spec/rails-2.3/rcov.opts +2 -0
  27. data/spec/rails-2.3/spec/spec_helper.rb +25 -0
  28. data/spec/rails-2.3/spec.opts +4 -0
  29. data/spec/rails-3.0/.rspec +2 -0
  30. data/spec/rails-3.0/Gemfile +12 -0
  31. data/spec/rails-3.0/Rakefile +11 -0
  32. data/spec/rails-3.0/app_root/.gitignore +4 -0
  33. data/spec/rails-3.0/app_root/config/application.rb +33 -0
  34. data/spec/rails-3.0/app_root/config/boot.rb +15 -0
  35. data/spec/rails-3.0/app_root/config/database.yml +6 -0
  36. data/spec/rails-3.0/app_root/config/environment.rb +7 -0
  37. data/spec/rails-3.0/app_root/config/environments/test.rb +37 -0
  38. data/spec/rails-3.0/app_root/config/initializers/backtrace_silencers.rb +9 -0
  39. data/spec/rails-3.0/app_root/config/initializers/inflections.rb +12 -0
  40. data/spec/rails-3.0/app_root/config/initializers/mime_types.rb +7 -0
  41. data/spec/rails-3.0/app_root/config/initializers/secret_token.rb +9 -0
  42. data/spec/rails-3.0/app_root/config/initializers/session_store.rb +10 -0
  43. data/spec/rails-3.0/app_root/config/routes.rb +5 -0
  44. data/spec/rails-3.0/app_root/lib/tasks/.gitkeep +0 -0
  45. data/spec/rails-3.0/app_root/log/.gitkeep +0 -0
  46. data/spec/rails-3.0/app_root/script/rails +6 -0
  47. data/spec/rails-3.0/rcov.opts +2 -0
  48. data/spec/rails-3.0/spec/spec_helper.rb +23 -0
  49. data/spec/rails-3.2/.rspec +2 -0
  50. data/spec/rails-3.2/Gemfile +13 -0
  51. data/spec/rails-3.2/Rakefile +11 -0
  52. data/spec/rails-3.2/app_root/.gitignore +4 -0
  53. data/spec/rails-3.2/app_root/config/application.rb +33 -0
  54. data/spec/rails-3.2/app_root/config/boot.rb +15 -0
  55. data/spec/rails-3.2/app_root/config/database.yml +6 -0
  56. data/spec/rails-3.2/app_root/config/environment.rb +7 -0
  57. data/spec/rails-3.2/app_root/config/environments/test.rb +37 -0
  58. data/spec/rails-3.2/app_root/config/initializers/backtrace_silencers.rb +9 -0
  59. data/spec/rails-3.2/app_root/config/initializers/inflections.rb +12 -0
  60. data/spec/rails-3.2/app_root/config/initializers/mime_types.rb +7 -0
  61. data/spec/rails-3.2/app_root/config/initializers/secret_token.rb +9 -0
  62. data/spec/rails-3.2/app_root/config/initializers/session_store.rb +10 -0
  63. data/spec/rails-3.2/app_root/config/routes.rb +5 -0
  64. data/spec/rails-3.2/app_root/log/.gitignore +1 -0
  65. data/spec/rails-3.2/rcov.opts +2 -0
  66. data/spec/rails-3.2/spec/spec_helper.rb +25 -0
  67. data/spec/shared/app_root/app/controllers/application_controller.rb +5 -0
  68. data/spec/shared/app_root/app/models/allow_setting_id_on_create.rb +21 -0
  69. data/spec/shared/app_root/app/models/forum.rb +10 -0
  70. data/spec/shared/app_root/app/models/post.rb +9 -0
  71. data/spec/shared/app_root/app/models/profile.rb +8 -0
  72. data/spec/shared/app_root/app/models/topic.rb +12 -0
  73. data/spec/shared/app_root/app/models/user.rb +12 -0
  74. data/spec/shared/app_root/config/database.sample.yml +6 -0
  75. data/spec/shared/app_root/config/database.travis_ci.yml +6 -0
  76. data/spec/shared/app_root/db/migrate/001_create_test_tables.rb +45 -0
  77. data/spec/shared/spec/edge_rider/collect_column_spec.rb +50 -0
  78. data/spec/shared/spec/edge_rider/collect_ids_spec.rb +73 -0
  79. data/spec/shared/spec/edge_rider/to_id_query_spec.rb +29 -0
  80. data/spec/shared/spec/edge_rider/to_sql_spec.rb +14 -0
  81. data/spec/shared/spec/edge_rider/traverse_association_spec.rb +133 -0
  82. data/spec/shared/spec/edge_rider/util_spec.rb +5 -0
  83. metadata +159 -0
@@ -0,0 +1,73 @@
1
+ require 'spec_helper'
2
+
3
+ describe EdgeRider::CollectIds do
4
+
5
+ describe '#collect_ids' do
6
+
7
+ context 'when called on an ActiveRecord class' do
8
+
9
+ it 'should return the ids for all records of that class' do
10
+ Forum.create!(:id => 1)
11
+ Forum.create!(:id => 2)
12
+ Forum.collect_ids.should =~ [1, 2]
13
+ end
14
+
15
+ end
16
+
17
+ context 'when called on a scope' do
18
+
19
+ it 'should return the ids for all records matching that scope' do
20
+ Forum.create!(:id => 1, :name => 'Name 1')
21
+ Forum.create!(:id => 2, :name => 'Name 2')
22
+ Forum.create!(:id => 3, :name => 'Name 2')
23
+ scope = Forum.scoped(:conditions => { :name => 'Name 2' })
24
+ scope.collect_ids.should =~ [2, 3]
25
+ end
26
+
27
+ end
28
+
29
+ context 'when called on a Fixnum' do
30
+
31
+ it 'should return the number as an array with a single element' do
32
+ 5.collect_ids.should == [5]
33
+ end
34
+
35
+ end
36
+
37
+ context 'when called on another scalar value' do
38
+
39
+ it 'should not be defined' do
40
+ expect { "foo".collect_ids }.to raise_error(NoMethodError)
41
+ end
42
+
43
+ end
44
+
45
+ context 'when called on an array of Fixnums' do
46
+
47
+ it 'should return the list itself' do
48
+ [1, 3].collect_ids.should == [1, 3]
49
+ end
50
+
51
+ end
52
+
53
+ context 'when called on an array of ActiveRecords' do
54
+
55
+ it 'should return the ids collected from that list' do
56
+ forum_1 = Forum.create!(:id => 1)
57
+ forum_2 = Forum.create!(:id => 2)
58
+ [forum_1, forum_2].collect_ids.should =~ [1, 2]
59
+ end
60
+
61
+ end
62
+
63
+ context 'when called on an array of other values' do
64
+
65
+ it 'should raise an error' do
66
+ expect { [1, 'foo', 3].collect_ids }.to raise_error(EdgeRider::CollectIds::Uncollectable)
67
+ end
68
+
69
+ end
70
+
71
+ end
72
+
73
+ end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+ describe EdgeRider::ToIdQuery do
4
+
5
+ describe '#to_id_query' do
6
+
7
+ it 'should simplify a scope to a IN query that selects IDs' do
8
+ Forum.create!(:id => 1, :name => 'Name 1')
9
+ Forum.create!(:id => 2, :name => 'Name 2')
10
+ Forum.create!(:id => 3, :name => 'Name 2')
11
+ scope = Forum.scoped(:conditions => { :name => 'Name 2' })
12
+ scope.to_id_query.to_sql.should =~ EdgeRider::Development.selects_star_with_conditions_pattern('forums', /`forums`\.`id` IN \(2,\s*3\)/)
13
+ end
14
+
15
+ it 'should resolve and lose any JOINs' do
16
+ Forum.create!(:id => 1, :name => 'A')
17
+ Forum.create!(:id => 2, :name => 'B')
18
+ Forum.create!(:id => 3, :name => 'A')
19
+ Topic.create!(:id => 100, :forum_id => 1)
20
+ Topic.create!(:id => 101, :forum_id => 1)
21
+ Topic.create!(:id => 102, :forum_id => 2)
22
+ Topic.create!(:id => 103, :forum_id => 3)
23
+ scope = Topic.scoped(:joins => :forum, :conditions => 'forums.name = "A"')
24
+ scope.to_id_query.to_sql.should =~ EdgeRider::Development.selects_star_with_conditions_pattern('topics', /`topics`\.`id` IN \(100,\s*101,\s*103\)/)
25
+ end
26
+
27
+ end
28
+
29
+ end
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+
3
+ describe EdgeRider::ToSql do
4
+
5
+ describe '#to_sql' do
6
+
7
+ it "should return the SQL the scope would produce" do
8
+ scope = Forum.scoped(:conditions => { :name => 'Name' })
9
+ scope.to_sql.should =~ EdgeRider::Development.selects_star_with_conditions_pattern('forums', "`forums`.`name` = 'Name'")
10
+ end
11
+
12
+ end
13
+
14
+ end
@@ -0,0 +1,133 @@
1
+ require 'spec_helper'
2
+
3
+ describe EdgeRider::TraverseAssociation do
4
+
5
+ describe '#traverse_association' do
6
+
7
+ it 'should traverse a belongs_to associations' do
8
+ forum_1 = Forum.create!
9
+ forum_2 = Forum.create!
10
+ forum_3 = Forum.create!
11
+ topic_1 = Topic.create!(:forum => forum_1)
12
+ topic_2 = Topic.create!(:forum => forum_1)
13
+ topic_3 = Topic.create!(:forum => forum_2)
14
+ topic_4 = Topic.create!(:forum => forum_3)
15
+ scope = Topic.scoped(:conditions => { :id => [ topic_2.id, topic_4.id ] })
16
+ traversed_scope = scope.traverse_association(:forum)
17
+ EdgeRider::Util.scope?(traversed_scope).should be_true
18
+ traversed_scope.to_a.should =~ [forum_1, forum_3]
19
+ end
20
+
21
+ it 'should raise an error when traversing a belongs_to association with conditions, until this is implemented' do
22
+ forum = Forum.create!(:trashed => true)
23
+ topic = Topic.create(:forum => forum)
24
+
25
+ scope = Topic.scoped(:conditions => { :id => topic.id })
26
+ expect { scope.traverse_association(:active_forum) }.to raise_error(NotImplementedError)
27
+ end
28
+
29
+ it 'should traverse a belongs_to association with conditions'
30
+
31
+ it 'should traverse multiple belongs_to associations in different model classes' do
32
+ forum_1 = Forum.create!
33
+ forum_2 = Forum.create!
34
+ forum_3 = Forum.create!
35
+ topic_1 = Topic.create!(:forum => forum_1)
36
+ topic_2 = Topic.create!(:forum => forum_2)
37
+ topic_3 = Topic.create!(:forum => forum_3)
38
+ post_1 = Post.create!(:topic => topic_1)
39
+ post_2 = Post.create!(:topic => topic_2)
40
+ post_3 = Post.create!(:topic => topic_3)
41
+ scope = Post.scoped(:conditions => { :id => [post_1.id, post_3.id] })
42
+ traversed_scope = scope.traverse_association(:topic, :forum)
43
+ EdgeRider::Util.scope?(traversed_scope).should be_true
44
+ traversed_scope.to_a.should =~ [forum_1, forum_3]
45
+ end
46
+
47
+ it 'should traverse one or more has_many associations' do
48
+ forum_1 = Forum.create!
49
+ forum_2 = Forum.create!
50
+ forum_3 = Forum.create!
51
+ topic_1 = Topic.create!(:forum => forum_1)
52
+ topic_2 = Topic.create!(:forum => forum_2)
53
+ topic_3 = Topic.create!(:forum => forum_3)
54
+ post_1 = Post.create!(:topic => topic_1)
55
+ post_2 = Post.create!(:topic => topic_2)
56
+ post_3a = Post.create!(:topic => topic_3)
57
+ post_3b = Post.create!(:topic => topic_3)
58
+ scope = Forum.scoped(:conditions => { :id => [forum_1.id, forum_3.id] })
59
+ traversed_scope = scope.traverse_association(:topics, :posts)
60
+ EdgeRider::Util.scope?(traversed_scope).should be_true
61
+ traversed_scope.to_a.should =~ [post_1, post_3a, post_3b]
62
+ end
63
+
64
+ it 'should raise an error when traversing a has_many association with conditions, until this is implemented' do
65
+ forum = Forum.create!
66
+ topic = Topic.create(:forum => forum, :trashed => true)
67
+
68
+ scope = Forum.scoped(:conditions => { :id => forum.id })
69
+ expect { scope.traverse_association(:active_topics) }.to raise_error(NotImplementedError)
70
+ end
71
+
72
+ it 'should traverse a has_many association with conditions'
73
+
74
+ it 'should traverse a has_many :through association' do
75
+ forum_1 = Forum.create!
76
+ forum_2 = Forum.create!
77
+ forum_3 = Forum.create!
78
+ topic_1 = Topic.create!(:forum => forum_1)
79
+ topic_2 = Topic.create!(:forum => forum_2)
80
+ topic_3 = Topic.create!(:forum => forum_3)
81
+ post_1 = Post.create!(:topic => topic_1)
82
+ post_2 = Post.create!(:topic => topic_2)
83
+ post_3a = Post.create!(:topic => topic_3)
84
+ post_3b = Post.create!(:topic => topic_3)
85
+ scope = Forum.scoped(:conditions => { :id => [forum_1.id, forum_3.id] })
86
+ traversed_scope = scope.traverse_association(:posts)
87
+ EdgeRider::Util.scope?(traversed_scope).should be_true
88
+ traversed_scope.to_a.should =~ [post_1, post_3a, post_3b]
89
+ end
90
+
91
+ it 'should traverse a has_one association' do
92
+ user_1 = User.create!
93
+ user_2 = User.create!
94
+ user_3 = User.create!
95
+ profile_1 = Profile.create!(:user => user_1)
96
+ profile_2 = Profile.create!(:user => user_2)
97
+ profile_3 = Profile.create!(:user => user_3)
98
+ scope = User.scoped(:conditions => { :id => [user_2.id, user_3.id] })
99
+ traversed_scope = scope.traverse_association(:profile)
100
+ EdgeRider::Util.scope?(traversed_scope).should be_true
101
+ traversed_scope.to_a.should =~ [profile_2, profile_3]
102
+ end
103
+
104
+ it 'should raise an error when traversing a has_many association with conditions, until this is implemented' do
105
+ user = User.create!
106
+ profile = Profile.create(:user => user, :trashed => true)
107
+
108
+ scope = User.scoped(:conditions => { :id => user.id })
109
+ expect { scope.traverse_association(:active_profile) }.to raise_error(NotImplementedError)
110
+ end
111
+
112
+ it 'should traverse a has_one association with conditions'
113
+
114
+ it 'should traverse up and down the same edges' do
115
+ forum_1 = Forum.create!
116
+ forum_2 = Forum.create!
117
+ forum_3 = Forum.create!
118
+ topic_1 = Topic.create!(:forum => forum_1)
119
+ topic_2 = Topic.create!(:forum => forum_2)
120
+ topic_3 = Topic.create!(:forum => forum_3)
121
+ post_1 = Post.create!(:topic => topic_1)
122
+ post_2 = Post.create!(:topic => topic_2)
123
+ post_3a = Post.create!(:topic => topic_3)
124
+ post_3b = Post.create!(:topic => topic_3)
125
+ scope = Post.scoped(:conditions => { :id => [post_3a.id] })
126
+ traversed_scope = scope.traverse_association(:topic, :forum, :topics, :posts)
127
+ EdgeRider::Util.scope?(traversed_scope).should be_true
128
+ traversed_scope.to_a.should =~ [post_3a, post_3b]
129
+ end
130
+
131
+ end
132
+
133
+ end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe EdgeRider::Util do
4
+
5
+ end
metadata ADDED
@@ -0,0 +1,159 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: edge_rider
3
+ version: !ruby/object:Gem::Version
4
+ hash: 25
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 1
10
+ version: 0.1.1
11
+ platform: ruby
12
+ authors:
13
+ - Henning Koch
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2013-02-11 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: rails
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 3
29
+ segments:
30
+ - 0
31
+ version: "0"
32
+ type: :runtime
33
+ version_requirements: *id001
34
+ description: Power tools for ActiveRecord relations (scopes)
35
+ email: henning.koch@makandra.de
36
+ executables: []
37
+
38
+ extensions: []
39
+
40
+ extra_rdoc_files: []
41
+
42
+ files:
43
+ - .gitignore
44
+ - .rvmrc
45
+ - .travis.yml
46
+ - README.md
47
+ - Rakefile
48
+ - edge_rider.gemspec
49
+ - lib/edge_rider.rb
50
+ - lib/edge_rider/collect_column.rb
51
+ - lib/edge_rider/collect_ids.rb
52
+ - lib/edge_rider/development.rb
53
+ - lib/edge_rider/to_id_query.rb
54
+ - lib/edge_rider/to_sql.rb
55
+ - lib/edge_rider/traverse_association.rb
56
+ - lib/edge_rider/util.rb
57
+ - lib/edge_rider/version.rb
58
+ - spec/rails-2.3/Gemfile
59
+ - spec/rails-2.3/Rakefile
60
+ - spec/rails-2.3/app_root/config/boot.rb
61
+ - spec/rails-2.3/app_root/config/database.yml
62
+ - spec/rails-2.3/app_root/config/environment.rb
63
+ - spec/rails-2.3/app_root/config/environments/test.rb
64
+ - spec/rails-2.3/app_root/config/initializers/fix_missing_source_file.rb
65
+ - spec/rails-2.3/app_root/config/preinitializer.rb
66
+ - spec/rails-2.3/app_root/config/routes.rb
67
+ - spec/rails-2.3/app_root/log/.gitignore
68
+ - spec/rails-2.3/rcov.opts
69
+ - spec/rails-2.3/spec.opts
70
+ - spec/rails-2.3/spec/spec_helper.rb
71
+ - spec/rails-3.0/.rspec
72
+ - spec/rails-3.0/Gemfile
73
+ - spec/rails-3.0/Rakefile
74
+ - spec/rails-3.0/app_root/.gitignore
75
+ - spec/rails-3.0/app_root/config/application.rb
76
+ - spec/rails-3.0/app_root/config/boot.rb
77
+ - spec/rails-3.0/app_root/config/database.yml
78
+ - spec/rails-3.0/app_root/config/environment.rb
79
+ - spec/rails-3.0/app_root/config/environments/test.rb
80
+ - spec/rails-3.0/app_root/config/initializers/backtrace_silencers.rb
81
+ - spec/rails-3.0/app_root/config/initializers/inflections.rb
82
+ - spec/rails-3.0/app_root/config/initializers/mime_types.rb
83
+ - spec/rails-3.0/app_root/config/initializers/secret_token.rb
84
+ - spec/rails-3.0/app_root/config/initializers/session_store.rb
85
+ - spec/rails-3.0/app_root/config/routes.rb
86
+ - spec/rails-3.0/app_root/lib/tasks/.gitkeep
87
+ - spec/rails-3.0/app_root/log/.gitkeep
88
+ - spec/rails-3.0/app_root/script/rails
89
+ - spec/rails-3.0/rcov.opts
90
+ - spec/rails-3.0/spec/spec_helper.rb
91
+ - spec/rails-3.2/.rspec
92
+ - spec/rails-3.2/Gemfile
93
+ - spec/rails-3.2/Rakefile
94
+ - spec/rails-3.2/app_root/.gitignore
95
+ - spec/rails-3.2/app_root/config/application.rb
96
+ - spec/rails-3.2/app_root/config/boot.rb
97
+ - spec/rails-3.2/app_root/config/database.yml
98
+ - spec/rails-3.2/app_root/config/environment.rb
99
+ - spec/rails-3.2/app_root/config/environments/test.rb
100
+ - spec/rails-3.2/app_root/config/initializers/backtrace_silencers.rb
101
+ - spec/rails-3.2/app_root/config/initializers/inflections.rb
102
+ - spec/rails-3.2/app_root/config/initializers/mime_types.rb
103
+ - spec/rails-3.2/app_root/config/initializers/secret_token.rb
104
+ - spec/rails-3.2/app_root/config/initializers/session_store.rb
105
+ - spec/rails-3.2/app_root/config/routes.rb
106
+ - spec/rails-3.2/app_root/log/.gitignore
107
+ - spec/rails-3.2/rcov.opts
108
+ - spec/rails-3.2/spec/spec_helper.rb
109
+ - spec/shared/app_root/app/controllers/application_controller.rb
110
+ - spec/shared/app_root/app/models/allow_setting_id_on_create.rb
111
+ - spec/shared/app_root/app/models/forum.rb
112
+ - spec/shared/app_root/app/models/post.rb
113
+ - spec/shared/app_root/app/models/profile.rb
114
+ - spec/shared/app_root/app/models/topic.rb
115
+ - spec/shared/app_root/app/models/user.rb
116
+ - spec/shared/app_root/config/database.sample.yml
117
+ - spec/shared/app_root/config/database.travis_ci.yml
118
+ - spec/shared/app_root/db/migrate/001_create_test_tables.rb
119
+ - spec/shared/spec/edge_rider/collect_column_spec.rb
120
+ - spec/shared/spec/edge_rider/collect_ids_spec.rb
121
+ - spec/shared/spec/edge_rider/to_id_query_spec.rb
122
+ - spec/shared/spec/edge_rider/to_sql_spec.rb
123
+ - spec/shared/spec/edge_rider/traverse_association_spec.rb
124
+ - spec/shared/spec/edge_rider/util_spec.rb
125
+ homepage: https://github.com/makandra/edge_rider
126
+ licenses: []
127
+
128
+ post_install_message:
129
+ rdoc_options: []
130
+
131
+ require_paths:
132
+ - lib
133
+ required_ruby_version: !ruby/object:Gem::Requirement
134
+ none: false
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ hash: 3
139
+ segments:
140
+ - 0
141
+ version: "0"
142
+ required_rubygems_version: !ruby/object:Gem::Requirement
143
+ none: false
144
+ requirements:
145
+ - - ">="
146
+ - !ruby/object:Gem::Version
147
+ hash: 3
148
+ segments:
149
+ - 0
150
+ version: "0"
151
+ requirements: []
152
+
153
+ rubyforge_project:
154
+ rubygems_version: 1.8.24
155
+ signing_key:
156
+ specification_version: 3
157
+ summary: Power tools for ActiveRecord relations (scopes)
158
+ test_files: []
159
+