randumb 0.4.1 → 0.5.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.
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