randumb 0.4.1 → 0.5.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: fd1f3d0262772918cb40ffc6f8c57bf5e841ea69
4
- data.tar.gz: 4f05d46fcee8600f14f287718adeb346b7832cf2
3
+ metadata.gz: b7a8de94fe998a9315531dc1785ccec096ed4a7e
4
+ data.tar.gz: b7e3d1440cc41ecd3231f8f9cde03361414cc329
5
5
  SHA512:
6
- metadata.gz: 0a713af87ffb2e625ee646dd9308876fbddb9c034d43eca825d6520bef18f8c6255d36771eafba17b770950fa4bdf17905558d4c81f1d5f542b95c12d9f714b8
7
- data.tar.gz: 1c8bfdab9e93a9bb3241a82115460e5d42c320aa1ac52484d2615314b076e8e7ad81618bd0d4021f83b091ba0aebbad90d110221e5d6b1b291d19e191b4517fb
6
+ metadata.gz: b215658a671a55d23fa68db3807ba2f2b6b204263ecb200f1a664f2f25bb58c0137132b1a67d4bbacaebf73ab7025f5a1348c7d2c722dc9f58837fa92faf024c
7
+ data.tar.gz: 7ea4b738b0cca2b7544bda4a55eb0e74c0e662cab6d85a46322086ddae7fa32def04afad55e82b5cb3fec8542a86116ca0ae00551803fdcc002695e665d0316b
@@ -10,36 +10,32 @@ module Randumb
10
10
  # If the max_items argument is omitted, one random entity will be returned.
11
11
  # If you provide the integer argument, you will get back an array of records.
12
12
  def random(max_items = nil, opts={})
13
- random_weighted(nil, max_items, opts)
13
+ ActiveSupport::Deprecation.warn "The random() method will be depricated in randumb 1.0 in favor of the order_by_rand scope."
14
+ relation = clone
15
+ return random_by_id_shuffle(max_items, opts) if is_randumb_postges_case?(relation)
16
+ scope = relation.order_by_rand(opts)
17
+
18
+ scope = scope.limit(max_items) if override_limit?(max_items, relation)
19
+
20
+ # return first record if method was called without parameters
21
+ max_items ? scope.to_a : scope.first
14
22
  end
15
23
 
16
24
  # If ranking_column is provided, that named column wil be multiplied
17
25
  # by a random number to determine probability of order. The ranking column must be numeric.
18
26
  def random_weighted(ranking_column, max_items = nil, opts={})
27
+ ActiveSupport::Deprecation.warn "The random_weighted() method will be depricated in randumb 1.0 in favor of the order_by_rand_weighted scope."
19
28
  relation = clone
20
29
  return random_by_id_shuffle(max_items, opts) if is_randumb_postges_case?(relation, ranking_column)
21
30
  raise_unless_valid_ranking_column(ranking_column)
22
31
 
23
- # get clause for current db type
24
- order_clause = Randumb::Syntax.random_order_clause(ranking_column, opts.merge(connection: connection, table_name: table_name))
32
+ scope = relation.order_by_rand_weighted(ranking_column, opts)
25
33
 
26
- the_scope = if ::ActiveRecord::VERSION::MAJOR == 3 && ::ActiveRecord::VERSION::MINOR < 2
27
- # AR 3.0.0 support
28
- relation.order(order_clause)
29
- else
30
- # keep prior orders and append random
31
- all_orders = (relation.orders + [order_clause]).join(", ")
32
- # override all previous orders
33
- relation.reorder(all_orders)
34
- end
35
-
36
34
  # override the limit if they are requesting multiple records
37
- if max_items && (!relation.limit_value || relation.limit_value > max_items)
38
- the_scope = the_scope.limit(max_items)
39
- end
35
+ scope = scope.limit(max_items) if override_limit?(max_items, relation)
40
36
 
41
37
  # return first record if method was called without parameters
42
- max_items ? the_scope.to_a : the_scope.first
38
+ max_items ? scope.to_a : scope.first
43
39
  end
44
40
 
45
41
 
@@ -67,14 +63,44 @@ module Randumb
67
63
  return_first_record ? records.first : records
68
64
  end
69
65
 
66
+ def order_by_rand(opts={})
67
+ build_order_scope(opts)
68
+ end
69
+
70
+ def order_by_rand_weighted(ranking_column, opts={})
71
+ raise_unless_valid_ranking_column(ranking_column)
72
+ is_randumb_postges_case?(self, ranking_column)
73
+ build_order_scope(opts, ranking_column)
74
+ end
75
+
70
76
  private
71
77
 
78
+ def build_order_scope(options, ranking_column=nil)
79
+ opts = options.reverse_merge(connection: connection, table_name: table_name)
80
+
81
+ order_clause = if ranking_column
82
+ Randumb::Syntax.random_weighted_order_clause(ranking_column, opts)
83
+ else
84
+ Randumb::Syntax.random_order_clause(opts)
85
+ end
86
+
87
+ if ::ActiveRecord::VERSION::MAJOR == 3 && ::ActiveRecord::VERSION::MINOR < 2
88
+ # AR 3.0.0 support
89
+ order(order_clause)
90
+ else
91
+ # keep prior orders and append random
92
+ all_orders = (orders + [order_clause]).join(", ")
93
+ # override all previous orders
94
+ reorder(all_orders)
95
+ end
96
+ end
97
+
72
98
  # postgres won't let you do an order_by when also doing a distinct
73
99
  # let's just use the in-memory option in this case
74
- def is_randumb_postges_case?(relation, ranking_column)
100
+ def is_randumb_postges_case?(relation, ranking_column=nil)
75
101
  if relation.respond_to?(:uniq_value) && relation.uniq_value && connection.adapter_name =~ /(postgres|postgis)/i
76
102
  if ranking_column
77
- raise Exception, "random_weighted: not possible when using .uniq and the postgres/postgis db adapter"
103
+ raise Exception, "order_by_rand_weighted: not possible when using .uniq and the postgres/postgis db adapter"
78
104
  else
79
105
  return true
80
106
  end
@@ -102,7 +128,6 @@ module Randumb
102
128
 
103
129
  id_results = connection.select_all(id_only_relation.to_sql)
104
130
 
105
-
106
131
  rng = random_number_generator(opts)
107
132
  if max_ids == 1 && id_results.count > 0
108
133
  rand_index = rng.rand(id_results.count)
@@ -122,6 +147,10 @@ module Randumb
122
147
  end
123
148
  end
124
149
 
150
+ def override_limit?(max_items, relation)
151
+ max_items && (!relation.limit_value || relation.limit_value > max_items)
152
+ end
153
+
125
154
  end
126
155
 
127
156
 
@@ -138,6 +167,14 @@ module Randumb
138
167
  def random_by_id_shuffle(max_items = nil, opts = {})
139
168
  relation.random_by_id_shuffle(max_items, opts)
140
169
  end
170
+
171
+ def order_by_rand(opts={})
172
+ relation.order_by_rand(opts)
173
+ end
174
+
175
+ def order_by_rand_weighted(ranking_column, opts={})
176
+ relation.order_by_rand_weighted(ranking_column, opts)
177
+ end
141
178
  end
142
179
 
143
180
 
@@ -145,6 +182,7 @@ module Randumb
145
182
  module MethodMissingMagicks
146
183
  def method_missing(symbol, *args)
147
184
  if symbol.to_s =~ /^random_weighted_by_(\w+)$/
185
+ ActiveSupport::Deprecation.warn "Dynamic finders will be removed in randumb 1.0 http://guides.rubyonrails.org/active_record_querying.html#dynamic-finders"
148
186
  random_weighted($1, *args)
149
187
  else
150
188
  super
@@ -153,6 +191,7 @@ module Randumb
153
191
 
154
192
  def respond_to?(symbol, include_private=false)
155
193
  if symbol.to_s =~ /^random_weighted_by_(\w+)$/
194
+ ActiveSupport::Deprecation.warn "Dynamic finders will be removed in randumb 1.0 http://guides.rubyonrails.org/active_record_querying.html#dynamic-finders"
156
195
  true
157
196
  else
158
197
  super
@@ -3,23 +3,25 @@ module Randumb
3
3
  class << self
4
4
 
5
5
  # builds the order clause to be appended in where clause
6
- def random_order_clause(ranking_column, opts={})
7
- if ranking_column.nil?
8
- random_for(opts)
6
+ def random_order_clause(opts={})
7
+ random_for(opts)
8
+ end
9
+
10
+ # builds the order clause to be appended in where clause
11
+ def random_weighted_order_clause(ranking_column, opts={})
12
+ connection = opts[:connection]
13
+
14
+ if connection.adapter_name =~ /sqlite/i
15
+ # computer multiplication is faster than division I was once taught...so translate here
16
+ max_int = 9223372036854775807.0
17
+ multiplier = 1.0 / max_int
18
+ "(#{ranking_column} * ABS(#{random_for(opts)} * #{multiplier}) ) DESC"
9
19
  else
10
- connection = opts[:connection]
11
- if connection.adapter_name =~ /sqlite/i
12
- # computer multiplication is faster than division I was once taught...so translate here
13
- max_int = 9223372036854775807.0
14
- multiplier = 1.0 / max_int
15
- "(#{ranking_column} * ABS(#{random_for(opts)} * #{multiplier}) ) DESC"
16
- else
17
- "(#{ranking_column} * #{random_for(opts)}) DESC"
18
- end
20
+ "(#{ranking_column} * #{random_for(opts)}) DESC"
19
21
  end
20
22
  end
21
23
 
22
- private
24
+ private
23
25
 
24
26
  # sligtly different for each DB
25
27
  def random_for(opts)
@@ -40,7 +42,7 @@ module Randumb
40
42
  if seed = opts[:seed]
41
43
  table_name = opts[:table_name]
42
44
  # SQLLite does not support a random seed. However, pseudo-randomness
43
- # can be achieved by sorting on a hash of the id field (generated by
45
+ # can be achieved by sorting on a hash of the id field (generated by
44
46
  # multiplying the id by the random seed and ignoring everything before
45
47
  # the decimal).
46
48
  # See http://stackoverflow.com/questions/2171578/seeding-sqlite-random
@@ -77,4 +79,4 @@ module Randumb
77
79
 
78
80
  end
79
81
  end
80
- end
82
+ end
@@ -1,3 +1,3 @@
1
1
  module Randumb
2
- VERSION = "0.4.1"
2
+ VERSION = "0.5.0"
3
3
  end
@@ -14,11 +14,13 @@ class RandumbTest < Test::Unit::TestCase
14
14
  # above is equivalent to:
15
15
  # assert_equal nil, Artist.random
16
16
  # assert_equal nil, Artist.random_by_id_shuffle
17
+ assert_nil Artist.order_by_rand.first
17
18
 
18
19
  assert_equal_for_both_methods [], Artist, 1
19
20
  # above is equivalent to:
20
21
  # assert_equal [], Artist.random(1)
21
22
  # assert_equal [], Artist.random_by_id_shuffle(1)
23
+ assert_equal [], Artist.order_by_rand.limit(1).all
22
24
 
23
25
  assert_equal_for_both_methods nil, Artist.limit(50)
24
26
  end
@@ -32,8 +34,11 @@ class RandumbTest < Test::Unit::TestCase
32
34
  assert_equal 1, Artist.count
33
35
 
34
36
  assert_equal_for_both_methods @high_on_fire, Artist
37
+ assert_equal @high_on_fire, Artist.order_by_rand.first
38
+
35
39
  assert_equal_for_both_methods [@high_on_fire], Artist, 1
36
40
  assert_equal_for_both_methods [@high_on_fire], Artist, 30
41
+ assert_equal [@high_on_fire], Artist.limit(30).order_by_rand.all
37
42
  end
38
43
 
39
44
  should "not return a record that doesnt match where" do
@@ -66,6 +71,10 @@ class RandumbTest < Test::Unit::TestCase
66
71
  assert_equal false, artists.first.name.nil?
67
72
  assert_raise (ActiveModel::MissingAttributeError) {artists.first.views}
68
73
 
74
+ artists = Artist.select(:name).order_by_rand.limit(3)
75
+ assert_equal false, artists.first.name.nil?
76
+ assert_raise (ActiveModel::MissingAttributeError) {artists.first.views}
77
+
69
78
  artists = Artist.select(:name).random_by_id_shuffle(3)
70
79
  assert_equal false, artists.first.name.nil?
71
80
  assert_raise (ActiveModel::MissingAttributeError) {artists.first.views}
@@ -73,6 +82,7 @@ class RandumbTest < Test::Unit::TestCase
73
82
 
74
83
  should "respect scopes" do
75
84
  assert_equal_for_both_methods [@fiona_apple], Artist.at_least_three_views, 3
85
+ assert_equal [@fiona_apple], Artist.at_least_three_views.order_by_rand.limit(3)
76
86
  end
77
87
 
78
88
  should "select only as many as in the db if we request more" do
@@ -200,6 +210,10 @@ class RandumbTest < Test::Unit::TestCase
200
210
  10.times do
201
211
  assert_equal seeded_order, Artist.random(2, seed: @seed)
202
212
  end
213
+
214
+ 10.times do
215
+ assert_equal seeded_order, Artist.order_by_rand(seed: @seed).limit(2)
216
+ end
203
217
  end
204
218
 
205
219
  should "always return the same order using shuffle method" do
@@ -59,3 +59,6 @@ class Test::Unit::TestCase
59
59
 
60
60
  end
61
61
 
62
+
63
+ # Silence deprications
64
+ ActiveSupport::Deprecation.silenced = true
@@ -4,7 +4,7 @@ class WeightedTest < Test::Unit::TestCase
4
4
 
5
5
  should "raise exception when called with a non-existent column" do
6
6
  assert_raises(ArgumentError) do
7
- Artist.random_weighted(:blah)
7
+ Artist.order_by_rand_weighted(:blah)
8
8
  end
9
9
  assert_raises(ArgumentError) do
10
10
  Artist.random_weighted_by_blah
@@ -13,7 +13,7 @@ class WeightedTest < Test::Unit::TestCase
13
13
 
14
14
  should "raise exception when called with a non-numeric column" do
15
15
  assert_raises(ArgumentError) do
16
- Artist.random_weighted(:name)
16
+ Artist.order_by_rand_weighted(:name)
17
17
  end
18
18
  assert_raises(ArgumentError) do
19
19
  Artist.random_weighted_by_name
@@ -25,7 +25,7 @@ class WeightedTest < Test::Unit::TestCase
25
25
  if ENV["DB"] == "postgres"
26
26
  should "raise exception if being called with uniq/postgres" do
27
27
  assert_raises(Exception) do
28
- Artist.uniq.random_weighted(:name)
28
+ Artist.uniq.order_by_rand_weighted(:views)
29
29
  end
30
30
  end
31
31
  else
@@ -66,6 +66,9 @@ class WeightedTest < Test::Unit::TestCase
66
66
  assert_hits_per_views do
67
67
  Artist.random_weighted("views").views
68
68
  end
69
+ assert_hits_per_views do
70
+ Artist.order_by_rand_weighted("views").first.views
71
+ end
69
72
  end
70
73
 
71
74
  should "order by ranking column with method_missing" do
@@ -80,6 +83,12 @@ class WeightedTest < Test::Unit::TestCase
80
83
  assert(result.size == 5)
81
84
  result.first.views
82
85
  end
86
+
87
+ assert_hits_per_views do
88
+ result = Artist.order_by_rand_weighted("views").limit(5).all
89
+ assert(result.size == 5)
90
+ result.first.views
91
+ end
83
92
  end
84
93
 
85
94
  should "order by ranking column with method_missing using max_items" do
@@ -98,6 +107,14 @@ class WeightedTest < Test::Unit::TestCase
98
107
  result.last.views
99
108
  end
100
109
  end
110
+
111
+ assert_raises(MiniTest::Assertion) do
112
+ assert_hits_per_views do
113
+ result = Artist.order_by_rand_weighted(:views).limit(3)
114
+ assert(result.size == 3)
115
+ result.last.views
116
+ end
117
+ end
101
118
  end
102
119
 
103
120
  should "order by ranking column with method_missing using 1 max_items" do
@@ -106,6 +123,12 @@ class WeightedTest < Test::Unit::TestCase
106
123
  assert(result.size == 1)
107
124
  result.first.views
108
125
  end
126
+
127
+ assert_hits_per_views do
128
+ result = Artist.order_by_rand_weighted(:views).limit(1)
129
+ assert(result.size == 1)
130
+ result.first.views
131
+ end
109
132
  end
110
133
  end
111
134
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: randumb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Zachary Kloepping
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-11-17 00:00:00.000000000 Z
11
+ date: 2014-03-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake