activerecord-deprecated_finders 0.0.1

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.
@@ -0,0 +1,176 @@
1
+ require 'active_record/relation'
2
+ require 'active_support/core_ext/module/aliasing'
3
+
4
+ module ActiveRecord
5
+ class Relation
6
+ module DeprecatedMethods
7
+ VALID_FIND_OPTIONS = [ :conditions, :include, :joins, :limit, :offset, :extend,
8
+ :order, :select, :readonly, :group, :having, :from, :lock ]
9
+
10
+ # The silence_deprecation arg is for internal use, where we have already output a
11
+ # deprecation further up the call stack.
12
+ def apply_finder_options(options, silence_deprecation = false)
13
+ ActiveSupport::Deprecation.warn("#apply_finder_options is deprecated") unless silence_deprecation
14
+
15
+ relation = clone
16
+ return relation unless options
17
+
18
+ options.assert_valid_keys(VALID_FIND_OPTIONS)
19
+ finders = options.dup
20
+ finders.delete_if { |key, value| value.nil? && key != :limit }
21
+
22
+ ((VALID_FIND_OPTIONS - [:conditions, :include, :extend]) & finders.keys).each do |finder|
23
+ relation = relation.send(finder, finders[finder])
24
+ end
25
+
26
+ relation = relation.where(finders[:conditions]) if options.has_key?(:conditions)
27
+ relation = relation.includes(finders[:include]) if options.has_key?(:include)
28
+ relation = relation.extending(finders[:extend]) if options.has_key?(:extend)
29
+
30
+ relation
31
+ end
32
+
33
+ def update_all_with_deprecated_options(updates, conditions = nil, options = {})
34
+ scope = self
35
+
36
+ if conditions
37
+ scope = where(conditions)
38
+
39
+ ActiveSupport::Deprecation.warn(
40
+ "Relation#update_all with conditions is deprecated. Please use " \
41
+ "Item.where(color: 'red').update_all(...) rather than " \
42
+ "Item.update_all(..., color: 'red')."
43
+ )
44
+ end
45
+
46
+ if options.present?
47
+ scope = scope.apply_finder_options(options.slice(:limit, :order), true)
48
+
49
+ ActiveSupport::Deprecation.warn(
50
+ "Relation#update_all with :limit / :order options is deprecated. " \
51
+ "Please use e.g. Post.limit(1).order(:foo).update_all instead."
52
+ )
53
+ end
54
+
55
+ scope.update_all_without_deprecated_options(updates)
56
+ end
57
+
58
+ def find_in_batches(options = {}, &block)
59
+ if (finder_options = options.except(:start, :batch_size)).present?
60
+ ActiveSupport::Deprecation.warn(
61
+ "Relation#find_in_batches with finder options is deprecated. Please build " \
62
+ "a scope and then call find_in_batches on it instead."
63
+ )
64
+
65
+ raise "You can't specify an order, it's forced to be #{batch_order}" if options[:order].present?
66
+ raise "You can't specify a limit, it's forced to be the batch_size" if options[:limit].present?
67
+
68
+ apply_finder_options(finder_options, true).
69
+ find_in_batches(options.slice(:start, :batch_size), &block)
70
+ else
71
+ super
72
+ end
73
+ end
74
+
75
+ def calculate(operation, column_name, options = {})
76
+ if options.except(:distinct).present?
77
+ ActiveSupport::Deprecation.warn(
78
+ "Relation#calculate with finder options is deprecated. Please build " \
79
+ "a scope and then call find_in_batches on it instead."
80
+ )
81
+
82
+ apply_finder_options(options.except(:distinct), true)
83
+ .calculate(operation, column_name, :distinct => options[:distinct])
84
+ else
85
+ super
86
+ end
87
+ end
88
+
89
+ def find(*args)
90
+ options = args.extract_options!
91
+
92
+ if options.present?
93
+ scope = apply_finder_options(options, true)
94
+
95
+ case finder = args.first
96
+ when :first, :last, :all
97
+ ActiveSupport::Deprecation.warn(
98
+ "Calling #find(#{finder.inspect}) is deprecated. Please call " \
99
+ "##{finder} directly instead. You have also used finder options. " \
100
+ "These are also deprecated. Please build a scope instead of using " \
101
+ "finder options."
102
+ )
103
+
104
+ scope.send(finder)
105
+ else
106
+ ActiveSupport::Deprecation.warn(
107
+ "Passing options to #find is deprecated. Please build a scope " \
108
+ "and then call #find on it."
109
+ )
110
+
111
+ scope.find(*args)
112
+ end
113
+ else
114
+ case finder = args.first
115
+ when :first, :last, :all
116
+ ActiveSupport::Deprecation.warn(
117
+ "Calling #find(#{finder.inspect}) is deprecated. Please call " \
118
+ "##{finder} directly instead."
119
+ )
120
+
121
+ send(finder)
122
+ else
123
+ super
124
+ end
125
+ end
126
+ end
127
+
128
+ def first(*args)
129
+ if args.empty?
130
+ super
131
+ else
132
+ if args.first.kind_of?(Integer) || (loaded? && !args.first.kind_of?(Hash))
133
+ super
134
+ else
135
+ ActiveSupport::Deprecation.warn(
136
+ "Relation#first with finder options is deprecated. Please build " \
137
+ "a scope and then call #first on it instead."
138
+ )
139
+
140
+ apply_finder_options(args.first, true).first
141
+ end
142
+ end
143
+ end
144
+
145
+ def last(*args)
146
+ if args.empty?
147
+ super
148
+ else
149
+ if args.first.kind_of?(Integer) || (loaded? && !args.first.kind_of?(Hash))
150
+ super
151
+ else
152
+ ActiveSupport::Deprecation.warn(
153
+ "Relation#last with finder options is deprecated. Please build " \
154
+ "a scope and then call #last on it instead."
155
+ )
156
+
157
+ apply_finder_options(args.first, true).last
158
+ end
159
+ end
160
+ end
161
+
162
+ def all(*args)
163
+ ActiveSupport::Deprecation.warn(
164
+ "Relation#all is deprecated. If you want to eager-load a relation, you can " \
165
+ "call #load (e.g. `Post.where(published: true).load`). If you want " \
166
+ "to get an array of records from a relation, you can call #to_a (e.g. " \
167
+ "`Post.where(published: true).to_a`)."
168
+ )
169
+ apply_finder_options(args.first, true).to_a
170
+ end
171
+ end
172
+
173
+ include DeprecatedMethods
174
+ alias_method_chain :update_all, :deprecated_options
175
+ end
176
+ end
@@ -0,0 +1,5 @@
1
+ module ActiveRecord
2
+ module DeprecatedFinders
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
@@ -0,0 +1,67 @@
1
+ require 'helper'
2
+
3
+ describe 'associations' do
4
+ before do
5
+ @klass = Class.new(ActiveRecord::Base)
6
+ def @klass.name; 'Post'; end
7
+ @klass.table_name = 'posts'
8
+ end
9
+
10
+ it 'translates hash scope options into scopes' do
11
+ extension = Module.new
12
+
13
+ assert_deprecated do
14
+ @klass.has_many :comments, readonly: 'a', order: 'b', limit: 'c', group: 'd', having: 'e',
15
+ offset: 'f', select: 'g', uniq: 'h', include: 'i', conditions: 'j',
16
+ extend: extension
17
+ end
18
+
19
+ scope = @klass.new.comments
20
+
21
+ scope.readonly_value.must_equal 'a'
22
+ scope.order_values.must_equal ['b']
23
+ scope.limit_value.must_equal 'c'
24
+ scope.group_values.must_equal ['d']
25
+ scope.having_values.must_equal ['e']
26
+ scope.offset_value.must_equal 'f'
27
+ scope.select_values.must_equal ['g']
28
+ scope.uniq_value.must_equal 'h'
29
+ scope.includes_values.must_equal ['i']
30
+ scope.where_values.must_include 'j'
31
+ scope.extensions.must_equal [extension]
32
+ end
33
+
34
+ it 'supports proc where values' do
35
+ ActiveSupport::Deprecation.silence do
36
+ @klass.has_many :comments, conditions: proc { 'omg' }
37
+ end
38
+ @klass.new.comments.where_values.must_include 'omg'
39
+ @klass.joins(:comments).to_sql.must_include 'omg'
40
+ end
41
+
42
+ it 'supports proc where values which access the owner' do
43
+ ActiveSupport::Deprecation.silence do
44
+ @klass.has_many :comments, conditions: proc { title }
45
+ end
46
+ @klass.new(title: 'omg').comments.where_values.must_include 'omg'
47
+ end
48
+
49
+ it 'allows an extend option plus a block extension' do
50
+ mod = Module.new { def foo; 'foo'; end }
51
+ ActiveSupport::Deprecation.silence do
52
+ @klass.has_many(:comments, extend: mod) { def bar; 'bar'; end }
53
+ end
54
+
55
+ obj = @klass.new
56
+ obj.comments.foo.must_equal 'foo'
57
+ obj.comments.bar.must_equal 'bar'
58
+ end
59
+
60
+ it "allows a declaration with a scope with no options" do
61
+ ActiveSupport::Deprecation.silence do
62
+ @klass.has_many :comments, -> { limit 5 }
63
+ end
64
+ scope = @klass.new.comments
65
+ scope.limit_value.must_equal 5
66
+ end
67
+ end
@@ -0,0 +1,15 @@
1
+ require 'helper'
2
+
3
+ describe 'calculate' do
4
+ after do
5
+ Post.destroy_all
6
+ end
7
+
8
+ it 'supports finder options' do
9
+ Post.create id: 1
10
+ Post.create id: 2, title: 'foo'
11
+ Post.create id: 3, title: 'foo'
12
+
13
+ assert_deprecated { Post.calculate(:sum, :id, conditions: { title: 'foo' }) }.must_equal 5
14
+ end
15
+ end
@@ -0,0 +1,35 @@
1
+ require 'helper'
2
+
3
+ describe 'default scope' do
4
+ before do
5
+ Post.create(id: 1, title: 'foo lol')
6
+ Post.create(id: 2, title: 'foo omg')
7
+ Post.create(id: 3)
8
+
9
+ @klass = Class.new(Post)
10
+ @klass.table_name = 'posts'
11
+ end
12
+
13
+ after do
14
+ Post.delete_all
15
+ end
16
+
17
+ it 'works with a finder hash' do
18
+ assert_deprecated { @klass.default_scope conditions: { id: 1 } }
19
+ @klass.all.map(&:id).must_equal [1]
20
+ end
21
+
22
+ it 'works with a finder hash and a scope' do
23
+ @klass.default_scope { @klass.where("title like '%foo%'") }
24
+ ActiveSupport::Deprecation.silence do
25
+ @klass.default_scope conditions: "title like '%omg%'"
26
+ end
27
+
28
+ @klass.all.map(&:id).must_equal [2]
29
+ end
30
+
31
+ it 'works with a block that returns a hash' do
32
+ @klass.default_scope { { conditions: { id: 1 } } }
33
+ assert_deprecated { @klass.all.to_a }.map(&:id).must_equal [1]
34
+ end
35
+ end
@@ -0,0 +1,133 @@
1
+ require 'helper'
2
+
3
+ describe 'dynamic_methods' do
4
+ before do
5
+ @posts = [
6
+ Post.create(title: 'foo', category: '1'),
7
+ Post.create(title: 'bar', category: '1'),
8
+ Post.create(title: 'bar', category: '2')
9
+ ]
10
+ end
11
+
12
+ after do
13
+ Post.delete_all
14
+ Comment.delete_all
15
+ end
16
+
17
+ it 'supports find_all_by' do
18
+ assert_deprecated do
19
+ Post.find_all_by_title('bar').must_equal [@posts[1], @posts[2]]
20
+ Post.find_all_by_title_and_category('bar', '2').must_equal [@posts[2]]
21
+ end
22
+ end
23
+
24
+ it 'supports find_all_by with finder options' do
25
+ assert_deprecated do
26
+ Post.find_all_by_title('bar', conditions: { category: '1' }).must_equal [@posts[1]]
27
+ end
28
+ end
29
+
30
+ it 'supports find_last_by' do
31
+ assert_deprecated do
32
+ Post.find_last_by_title('foo').must_equal @posts[0]
33
+ Post.find_last_by_title('bar').must_equal @posts[2]
34
+ end
35
+ end
36
+
37
+ it 'supports find_last_by with finder options' do
38
+ assert_deprecated do
39
+ Post.find_last_by_title('bar', conditions: { category: '1' }).must_equal @posts[1]
40
+ end
41
+ end
42
+
43
+ it 'supports scoped_by' do
44
+ scope = assert_deprecated { Post.scoped_by_title('bar') }
45
+ scope.is_a?(ActiveRecord::Relation).must_equal true
46
+ scope.to_a.must_equal [@posts[1], @posts[2]]
47
+ end
48
+
49
+ it 'supports find_or_initialize_by' do
50
+ assert_deprecated { Post.find_or_initialize_by_title_and_category('bar', '1').must_equal @posts[1] }
51
+
52
+ post = assert_deprecated { Post.find_or_initialize_by_title_and_category('bar', '3') }
53
+ post.new_record?.must_equal true
54
+ post.title.must_equal 'bar'
55
+ post.category.must_equal '3'
56
+ end
57
+
58
+ it 'supports find_or_create_by' do
59
+ assert_deprecated { Post.find_or_create_by_title_and_category('bar', '1').must_equal @posts[1] }
60
+
61
+ post = assert_deprecated { Post.find_or_create_by_title_and_category('bar', '3') }
62
+ post.new_record?.must_equal false
63
+ post.title.must_equal 'bar'
64
+ post.category.must_equal '3'
65
+ end
66
+
67
+ it 'supports find_or_create_by!' do
68
+ assert_deprecated { Post.find_or_create_by_title_and_category!('bar', '1').must_equal @posts[1] }
69
+
70
+ post = assert_deprecated { Post.find_or_create_by_title_and_category!('bar', '3') }
71
+ post.new_record?.must_equal false
72
+ post.title.must_equal 'bar'
73
+ post.category.must_equal '3'
74
+
75
+ klass = Class.new(ActiveRecord::Base)
76
+ def klass.name; 'Post'; end
77
+ klass.table_name = 'posts'
78
+ klass.validates_presence_of :category
79
+
80
+ lambda {
81
+ ActiveSupport::Deprecation.silence { klass.find_or_create_by_title!('z') }
82
+ }.must_raise ActiveRecord::RecordInvalid
83
+ end
84
+
85
+ it 'supports find_by with finder options' do
86
+ assert_deprecated do
87
+ Post.find_by_title('bar', conditions: { category: '2' }).must_equal @posts[2]
88
+ end
89
+ end
90
+
91
+ it 'supports find_by! with finder options' do
92
+ assert_deprecated do
93
+ Post.find_by_title!('bar', conditions: { category: '2' }).must_equal @posts[2]
94
+ end
95
+
96
+ lambda {
97
+ assert_deprecated { Post.find_by_title!('bar', conditions: { category: '3' }) }
98
+ }.must_raise ActiveRecord::RecordNotFound
99
+ end
100
+
101
+ it 'supports find_by with a block' do
102
+ assert_deprecated do
103
+ Post.find_by_title('foo') { |r| [r, 'block'] }.must_equal [@posts[0], 'block']
104
+ Post.find_by_title('baz') { |r| [r, 'block'] }.must_equal nil
105
+ end
106
+ end
107
+
108
+ it 'supports find_by! with a block' do
109
+ assert_deprecated do
110
+ Post.find_by_title!('foo') { |r| [r, 'block'] }.must_equal [@posts[0], 'block']
111
+ end
112
+ end
113
+
114
+ it 'adds to an association when find_or_initialize_by is called' do
115
+ post = @posts.first
116
+ comment = ActiveSupport::Deprecation.silence { post.comments.find_or_initialize_by_title('omg') }
117
+ post.comments.must_equal [comment]
118
+ end
119
+
120
+ it 'adds to an association when find_or_create_by is called' do
121
+ post = @posts.first
122
+ post.comments.load_target
123
+
124
+ comment = ActiveSupport::Deprecation.silence { post.comments.find_or_create_by_title('omg') }
125
+ post.comments.must_equal [comment]
126
+ post.reload.comments.must_equal [comment]
127
+ end
128
+
129
+ it "doesn't mess with method_missing for non-find_or_{initialize|create}_by methods" do
130
+ post = @posts.first
131
+ post.comments.lol.must_equal 'lol'
132
+ end
133
+ end
@@ -0,0 +1,18 @@
1
+ require 'helper'
2
+
3
+ describe 'find_in_batches' do
4
+ after do
5
+ Post.destroy_all
6
+ end
7
+
8
+ it 'accepts finder options' do
9
+ foo = Post.create title: 'foo'
10
+ Post.create title: 'bar'
11
+
12
+ assert_deprecated do
13
+ Post.find_in_batches(conditions: "title = 'foo'") do |records|
14
+ records.must_equal [foo]
15
+ end
16
+ end
17
+ end
18
+ end