ar-ondemand 1.1.5 → 1.1.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- NDhlMjQ2ZTkzNjRkMTc0MmJiMGM3Y2VkYjQ1NDcwZDVlYTA4ZGQzNQ==
4
+ ZmZhMmNkZmQzM2E0M2RlOGVhY2NkZDJmMjE1OTBlNDQ2Zjg2Zjk4Mw==
5
5
  data.tar.gz: !binary |-
6
- Mzk5ZDY1OTdmZjg5YzEzZmI2YTNkNDNhMGI0MTliYzQ2Nzc0ZjU1Mw==
6
+ ZDFmNzAzZjRmN2E5ZTQ1NzM1NTdkNDEzZTA2YThlNGE5Yjc5OTlhMQ==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- OTRlYjk5NzhhZjU4MmVkOGViMGFjOTkyYWY2MjQ2ZGUxMmE3ZTFlMzE1NWZm
10
- YTQ1ZGFhZWI0NDZlYmUwMDUzYjA0OWIwMGJjMzM1OWRkMTcwNDliODIwZWVl
11
- NzZhN2QzMDc1MWMwY2UxMWI0ZTNhNThjMTFhODBkZjk4MTVjZWI=
9
+ ZDA3MDQzNTg2MDYyMjViNWYwYTdjNzVjOWJlOWYzZGM5Njc5NTlmYmYzNWMz
10
+ MzVlYzkwY2EyYzI2ZTJiNmE2ZTRkMzZjNzNjY2VhYjFkNDkwMzUxNDU1YTkz
11
+ YzRmNjBiMWJmMzg3YmM0YTUwNTk2OGE1NTQzZWQ2YThiYjRhYmI=
12
12
  data.tar.gz: !binary |-
13
- ZDRmOTExOTU0Y2E0ZmI0YjQ2YmUxZGVkOGVhMWU5YTlmNDU4N2FkM2JlYTVj
14
- N2Q0MWU1ZDI2NzViNjY0YTU2ZTU5ZTE2NzAyMmEyNGMzZjE5NTZiNjAyNDZh
15
- NmI1YjFkZWJiZDQ2YTdkNDY2OGQyMDNmOGQwMjYyYjk1YmI0ZjY=
13
+ YTA3MTE5ZDE4ZGM1ZGIxNzA0NzJmZjZiNmM3ZmE1Y2NlNjJjZjg3NTQxYWI0
14
+ OGRjOGZhNWM1M2Q5NTE4ZWRlZGMzYzM0MWM4YmI0OTRiYjk4MDY1NTEzMzdh
15
+ ZWNlZjcxYmZiZjljY2JmMGMzYmE4ZmJkN2NmMTc1NmIyMzlkZTA=
data/Gemfile CHANGED
@@ -11,7 +11,5 @@ group :test, :development do
11
11
 
12
12
  gem 'rspec'
13
13
  gem 'factory_girl'
14
- gem 'shoulda'
15
- gem 'shoulda-matchers'
16
14
  gem 'pry'
17
15
  end
data/Gemfile.lock CHANGED
@@ -1,54 +1,53 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ar-ondemand (1.1.5)
5
- activerecord (>= 3.2)
6
- activesupport (>= 3.2)
4
+ ar-ondemand (1.1.6)
5
+ activerecord (~> 3.2)
6
+ activesupport (~> 3.2)
7
7
 
8
8
  GEM
9
9
  remote: http://rubygems.org/
10
10
  specs:
11
- activemodel (3.2.21)
12
- activesupport (= 3.2.21)
11
+ activemodel (3.2.22.5)
12
+ activesupport (= 3.2.22.5)
13
13
  builder (~> 3.0.0)
14
- activerecord (3.2.21)
15
- activemodel (= 3.2.21)
16
- activesupport (= 3.2.21)
14
+ activerecord (3.2.22.5)
15
+ activemodel (= 3.2.22.5)
16
+ activesupport (= 3.2.22.5)
17
17
  arel (~> 3.0.2)
18
18
  tzinfo (~> 0.3.29)
19
- activesupport (3.2.21)
19
+ activesupport (3.2.22.5)
20
20
  i18n (~> 0.6, >= 0.6.4)
21
21
  multi_json (~> 1.0)
22
22
  arel (3.0.3)
23
23
  builder (3.0.4)
24
- coderay (1.1.0)
24
+ coderay (1.1.1)
25
25
  diff-lcs (1.2.5)
26
- factory_girl (4.5.0)
26
+ factory_girl (4.7.0)
27
27
  activesupport (>= 3.0.0)
28
- i18n (0.6.11)
28
+ i18n (0.7.0)
29
29
  method_source (0.8.2)
30
- multi_json (1.10.1)
31
- pry (0.10.1)
30
+ multi_json (1.12.1)
31
+ pry (0.10.4)
32
32
  coderay (~> 1.1.0)
33
33
  method_source (~> 0.8.1)
34
34
  slop (~> 3.4)
35
- rspec (2.99.0)
36
- rspec-core (~> 2.99.0)
37
- rspec-expectations (~> 2.99.0)
38
- rspec-mocks (~> 2.99.0)
39
- rspec-core (2.99.2)
40
- rspec-expectations (2.99.2)
41
- diff-lcs (>= 1.1.3, < 2.0)
42
- rspec-mocks (2.99.2)
43
- shoulda (3.5.0)
44
- shoulda-context (~> 1.0, >= 1.0.1)
45
- shoulda-matchers (>= 1.4.1, < 3.0)
46
- shoulda-context (1.2.1)
47
- shoulda-matchers (2.7.0)
48
- activesupport (>= 3.0.0)
35
+ rspec (3.5.0)
36
+ rspec-core (~> 3.5.0)
37
+ rspec-expectations (~> 3.5.0)
38
+ rspec-mocks (~> 3.5.0)
39
+ rspec-core (3.5.4)
40
+ rspec-support (~> 3.5.0)
41
+ rspec-expectations (3.5.0)
42
+ diff-lcs (>= 1.2.0, < 2.0)
43
+ rspec-support (~> 3.5.0)
44
+ rspec-mocks (3.5.0)
45
+ diff-lcs (>= 1.2.0, < 2.0)
46
+ rspec-support (~> 3.5.0)
47
+ rspec-support (3.5.0)
49
48
  slop (3.6.0)
50
- sqlite3 (1.3.10)
51
- tzinfo (0.3.42)
49
+ sqlite3 (1.3.12)
50
+ tzinfo (0.3.52)
52
51
 
53
52
  PLATFORMS
54
53
  ruby
@@ -58,6 +57,4 @@ DEPENDENCIES
58
57
  factory_girl
59
58
  pry
60
59
  rspec
61
- shoulda
62
- shoulda-matchers
63
60
  sqlite3
data/README.md CHANGED
@@ -7,7 +7,7 @@ The `ar-ondemand` gem adds functionality to ActiveRecord to help deal with AR's
7
7
 
8
8
  # Getting Started
9
9
 
10
- ```
10
+ ```rb
11
11
  require 'ar-ondemand'
12
12
  ```
13
13
 
@@ -34,7 +34,7 @@ ActiveRecord model so that all the real functionality you'd expect, such as vali
34
34
 
35
35
  ### Usage
36
36
 
37
- ```
37
+ ```rb
38
38
  assets = Widget.on_demand :identifier, {customer_id: 1, account_id: 42}
39
39
  source.each do |dso|
40
40
  w = assets[dso[:identifier]]
@@ -57,13 +57,13 @@ method makes it easy to get access to ActiveRecord-like functionality at 100th t
57
57
 
58
58
  Let's say you have some Widget's. Instead of:
59
59
 
60
- ```
60
+ ```rb
61
61
  Widget.where(customer_id: 1).each { |r| ... }
62
62
  ```
63
63
 
64
64
  use `for_reading` and get a significant speed boost, and use far less memory:
65
65
 
66
- ```
66
+ ```rb
67
67
  Widget.where(customer_id: 1).for_reading.each { |r| ... }
68
68
  ```
69
69
 
@@ -71,24 +71,24 @@ The big limitation is that you can't use `.includes` so you have to be writing a
71
71
 
72
72
  ### Batch Results
73
73
 
74
- ```
74
+ ```rb
75
75
  Widget.where(customer_id: 1).for_reading(batch_size: 50000).each { |b| b.each { |r| } }
76
76
  ```
77
77
 
78
- ### raw_results
78
+ ## raw_results
79
79
 
80
80
  This is just a nice little helper to get the raw database results, which you'd get by calling `ActiveRecord::Base.connection.select_all`
81
81
  but for some reason you can't call that on a model.
82
82
 
83
- ```
83
+ ```rb
84
84
  ActiveRecord::Base.connection.select_all "select * from widgets"
85
85
  ActiveRecord::Base.connection.select_all "select * from widgets where customer_id = 1"
86
86
  ActiveRecord::Base.connection.select_all "select * from widgets where customer_id = 1 limit 100000"
87
87
  ```
88
88
 
89
- use:
89
+ ### Usage
90
90
 
91
- ```
91
+ ```rb
92
92
  Widget.raw_results
93
93
  Widget.where(customer_id: 1).raw_results
94
94
  Widget.where(customer_id: 1).limit(100_000).raw_results
@@ -103,7 +103,7 @@ change your code to use batching.
103
103
 
104
104
  ### Usage
105
105
 
106
- ```
106
+ ```rb
107
107
  def run
108
108
  get_objects.each do |r|
109
109
  do_something r
@@ -117,7 +117,7 @@ end
117
117
 
118
118
  Additional usage:
119
119
 
120
- ```
120
+ ```rb
121
121
  Widget.where(customer_id: 1).for_streaming(batch_size: 100_000).each { |r| }
122
122
  Widget.where(customer_id: 1).for_streaming(for_reading: true).each { |r| }
123
123
  Widget.where(customer_id: 1).for_streaming(for_reading: true, batch_size: 1_000_000).each { |r| }
@@ -132,13 +132,13 @@ the primary keys as the `where` condition. This function does that all for you.
132
132
 
133
133
  ### Usage
134
134
 
135
- ```
135
+ ```rb
136
136
  Widget.delete_all_by_pk
137
137
  Widget.where(Widget[:customer_id].eq(1).and(Widget[:usage].gt(42))).delete_all_by_pk
138
138
  ```
139
139
 
140
140
  If you know you could be deleting millions, then we recommend batching the deletes:
141
141
 
142
- ```
142
+ ```rb
143
143
  Widget.where(Widget[:customer_id].eq(1).and(Widget[:usage].gt(42))).delete_all_by_pk(batch_size: 250_000)
144
144
  ```
data/ar-ondemand.gemspec CHANGED
@@ -20,6 +20,6 @@ Gem::Specification.new do |s|
20
20
 
21
21
  s.require_paths = %w(lib)
22
22
 
23
- s.add_dependency 'activesupport', '>= 3.2'
24
- s.add_dependency 'activerecord', '>= 3.2'
25
- end
23
+ s.add_dependency 'activesupport', '~> 3.2'
24
+ s.add_dependency 'activerecord', '~> 3.2'
25
+ end
data/lib/ar-ondemand.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require_dependency 'ar-ondemand/on_demand'
2
2
  require_dependency 'ar-ondemand/for_reading'
3
3
  require_dependency 'ar-ondemand/for_streaming'
4
- require_dependency 'ar-ondemand/delete_all_by_pk'
4
+ require_dependency 'ar-ondemand/for_enumeration_reading'
5
+ require_dependency 'ar-ondemand/delete_all_by_pk'
@@ -0,0 +1,38 @@
1
+ module ActiveRecord
2
+ module OnDemand
3
+ class FastEnumeration
4
+
5
+ def initialize(model, result_set)
6
+ @result_set = result_set
7
+
8
+ result_set.columns.each_with_index do |name, index|
9
+ self.define_singleton_method(name) {
10
+ raise "Not accessible outside of enumeration" if @row.nil?
11
+ @row[index]
12
+ }
13
+ end
14
+ end
15
+
16
+ def each
17
+ @result_set.rows.each do |r|
18
+ @row = r
19
+ yield(self)
20
+ nil
21
+ end
22
+ ensure
23
+ @row = nil
24
+ end
25
+
26
+ def inject(inj)
27
+ @result_set.rows.each do |r|
28
+ @row = r
29
+ inj = yield(inj, self)
30
+ end
31
+ inj
32
+ ensure
33
+ @row = nil
34
+ end
35
+
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,27 @@
1
+ require 'active_support/concern'
2
+ require 'ar-ondemand/fast_enumeration'
3
+
4
+ module ActiveRecord
5
+ module OnDemand
6
+ module EnumerationReading
7
+ extend ::ActiveSupport::Concern
8
+
9
+ module ClassMethods
10
+ def for_enumeration_reading
11
+ query_for_enumeration_reading self
12
+ end
13
+
14
+ private
15
+ def query_for_enumeration_reading(ar)
16
+ ar = ar.scoped unless ar.respond_to?(:to_sql)
17
+ ::ActiveRecord::OnDemand::FastEnumeration.new(ar.arel.engine, ::ActiveRecord::Base.connection.exec_query(ar.to_sql))
18
+ end
19
+
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ ::ActiveRecord::Base.send :include, ::ActiveRecord::OnDemand::EnumerationReading
26
+ ::ActiveRecord::Relation.send :include, ::ActiveRecord::OnDemand::EnumerationReading::ClassMethods
27
+
@@ -19,7 +19,6 @@ module ActiveRecord
19
19
  @key_index = @col_indexes[@key_column]
20
20
  raise "Unknown index #{key_column}" if @key_index.nil?
21
21
 
22
- @find_by_method = "find_or_initialize_by_#{(@defaults.keys + [@key_column]).join('_and_')}"
23
22
  @has_any_assets = !ids.empty? || @model.unscoped.where(@defaults).exists?
24
23
  @new_params = @defaults.dup
25
24
  @new_params[@key_column.to_sym] = nil
@@ -28,7 +27,7 @@ module ActiveRecord
28
27
  h[row[@key_index]] = row
29
28
  h
30
29
  end
31
-
30
+
32
31
  self
33
32
  end
34
33
 
@@ -37,8 +36,9 @@ module ActiveRecord
37
36
  rec = @results_to_hash[key]
38
37
  if rec.nil?
39
38
  rec = if @has_any_assets
40
- args = @defaults.values + [key]
41
- @model.unscoped.send(@find_by_method, *args)
39
+ @model.unscoped
40
+ .where(@defaults.merge(@key_column => key))
41
+ .first_or_initialize
42
42
  else
43
43
  @new_params[@key_column.to_sym] = key
44
44
  @model.new @new_params
@@ -1,3 +1,3 @@
1
1
  module ArOnDemand
2
- VERSION = '1.1.5'
2
+ VERSION = '1.1.6'
3
3
  end
@@ -9,7 +9,7 @@ describe 'DeleteAllByPk' do
9
9
  end
10
10
 
11
11
  it 'should delete record' do
12
- AuditRecord.delete_all_by_pk.should eq(1)
12
+ expect(AuditRecord.delete_all_by_pk).to be 1
13
13
  end
14
14
  end
15
15
 
@@ -19,8 +19,8 @@ describe 'DeleteAllByPk' do
19
19
  end
20
20
 
21
21
  it 'should delete record' do
22
- AuditRecord.where('id > 0').delete_all_by_pk.should eq(1)
22
+ expect(AuditRecord.where('id > 0').delete_all_by_pk).to be 1
23
23
  end
24
24
  end
25
25
  end
26
- end
26
+ end
@@ -0,0 +1,74 @@
1
+ require 'spec_helper'
2
+ require 'ar-ondemand'
3
+
4
+ describe 'ForEnumerationReading' do
5
+ context 'Testing' do
6
+ context 'Ensure Persistance Works' do
7
+ before(:each) do
8
+ create(:audit_record)
9
+ end
10
+
11
+ it 'should do persist' do
12
+ expect(AuditRecord.all.length).to be 1
13
+ end
14
+
15
+ it 'should do foo' do
16
+ expect(AuditRecord.first.action).to eq 'create'
17
+ end
18
+ end
19
+
20
+ context 'Iterating' do
21
+ before(:each) do
22
+ (1..25).each do
23
+ create(:audit_record)
24
+ end
25
+ end
26
+
27
+ it 'should support iterating' do
28
+ total = 0
29
+ AuditRecord.where(customer_id: 1).for_enumeration_reading.each do |r|
30
+ total += 1
31
+ end
32
+ expect(total).to be 25
33
+ end
34
+
35
+ it 'should support inject iterating' do
36
+ inj = AuditRecord.where(customer_id: 1).for_enumeration_reading.inject([]) do |i,r|
37
+ i << r.id
38
+ end
39
+ expect(inj.size).to be 25
40
+ end
41
+
42
+ it 'should produce same results as regular iterating' do
43
+ records_a = Set.new
44
+ AuditRecord.where(customer_id: 1).for_enumeration_reading.each do |r|
45
+ records_a.add r.id
46
+ end
47
+
48
+ records_b = Set.new
49
+ AuditRecord.where(customer_id: 1).each do |r|
50
+ records_b.add r.id
51
+ end
52
+
53
+ expect(records_a).to eq records_b
54
+ end
55
+
56
+ it 'should not allow access outside each enumeration' do
57
+ obj = nil
58
+ AuditRecord.where(customer_id: 1).for_enumeration_reading.each do |r|
59
+ obj = r
60
+ end
61
+ expect{obj.id}.to raise_error(RuntimeError)
62
+ end
63
+
64
+ it 'should not allow access outside each inject enumeration' do
65
+ cache = AuditRecord.where(customer_id: 1).for_enumeration_reading.inject({}) do |h,r|
66
+ h[r.id] = r
67
+ h
68
+ end
69
+ expect{cache.first[1].id}.to raise_error(RuntimeError)
70
+ end
71
+
72
+ end
73
+ end
74
+ end
@@ -9,11 +9,11 @@ describe 'ForReading' do
9
9
  end
10
10
 
11
11
  it 'should do persist' do
12
- AuditRecord.all.length.should eq(1)
12
+ expect(AuditRecord.all.length).to be 1
13
13
  end
14
14
 
15
15
  it 'should do foo' do
16
- AuditRecord.first.action.should eq('create')
16
+ expect(AuditRecord.first.action).to eq 'create'
17
17
  end
18
18
  end
19
19
 
@@ -29,7 +29,7 @@ describe 'ForReading' do
29
29
  AuditRecord.where(customer_id: 1).for_reading.each do |r|
30
30
  total += 1
31
31
  end
32
- total.should eq(25)
32
+ expect(total).to be 25
33
33
  end
34
34
 
35
35
  it 'should support iterating' do
@@ -37,7 +37,7 @@ describe 'ForReading' do
37
37
  AuditRecord.for_reading.each do |r|
38
38
  total += 1
39
39
  end
40
- total.should eq(25)
40
+ expect(total).to be 25
41
41
  end
42
42
 
43
43
  it 'should produce same results as regular iterating' do
@@ -51,9 +51,9 @@ describe 'ForReading' do
51
51
  records_b.add r.id
52
52
  end
53
53
 
54
- records_a.should eq(records_b)
54
+ expect(records_a).to eq records_b
55
55
  end
56
56
 
57
57
  end
58
58
  end
59
- end
59
+ end
@@ -14,11 +14,10 @@ describe 'ForStreaming' do
14
14
  it 'ClassMethod should support streaming' do
15
15
  total = 0
16
16
  AuditRecord.for_streaming.each do |r|
17
- #r.is_a?(AuditRecord).should eq(true)
18
17
  expect(r).to be_an_instance_of(AuditRecord)
19
18
  total += 1
20
19
  end
21
- total.should eq(25)
20
+ expect(total).to be 25
22
21
  end
23
22
 
24
23
  it 'Relation should support streaming' do
@@ -27,7 +26,7 @@ describe 'ForStreaming' do
27
26
  expect(r).to be_an_instance_of(AuditRecord)
28
27
  total += 1
29
28
  end
30
- total.should eq(25)
29
+ expect(total).to be 25
31
30
  end
32
31
 
33
32
  it 'should support select' do
@@ -38,7 +37,7 @@ describe 'ForStreaming' do
38
37
  expect { r.model_type_id }.to raise_error(::ActiveModel::MissingAttributeError)
39
38
  total += 1
40
39
  end
41
- total.should eq(25)
40
+ expect(total).to be 25
42
41
  end
43
42
  end
44
43
 
@@ -47,23 +46,23 @@ describe 'ForStreaming' do
47
46
  total = 0
48
47
  AuditRecord.for_streaming(for_reading: true).each do |r|
49
48
  expect(r).not_to be_an_instance_of(AuditRecord)
50
- r.customer_id.should eq(1)
49
+ expect(r.customer_id).to be 1
51
50
  total += 1
52
51
  end
53
- total.should eq(25)
52
+ expect(total).to be 25
54
53
  end
55
54
 
56
55
  it 'Relation should support streaming' do
57
56
  total = 0
58
57
  AuditRecord.where(customer_id: 1).for_streaming(for_reading: true).each do |r|
59
58
  expect(r).not_to be_an_instance_of(AuditRecord)
60
- r.customer_id.should eq(1)
59
+ expect(r.customer_id).to be 1
61
60
  total += 1
62
61
  end
63
- total.should eq(25)
62
+ expect(total).to be 25
64
63
  end
65
64
  end
66
65
 
67
66
  end
68
67
  end
69
- end
68
+ end
@@ -5,9 +5,6 @@ ActiveRecord::Migration.suppress_messages do
5
5
  load 'spec/db/seeds.rb'
6
6
  end
7
7
 
8
- require 'shoulda'
9
- require 'shoulda/matchers/integrations/rspec'
10
-
11
8
  RSpec.configure do |config|
12
9
  config.around do |example|
13
10
  ActiveRecord::Base.transaction do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ar-ondemand
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.5
4
+ version: 1.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steve Frank
@@ -14,28 +14,28 @@ dependencies:
14
14
  name: activesupport
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ! '>='
17
+ - - ~>
18
18
  - !ruby/object:Gem::Version
19
19
  version: '3.2'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ! '>='
24
+ - - ~>
25
25
  - !ruby/object:Gem::Version
26
26
  version: '3.2'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: activerecord
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ! '>='
31
+ - - ~>
32
32
  - !ruby/object:Gem::Version
33
33
  version: '3.2'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ! '>='
38
+ - - ~>
39
39
  - !ruby/object:Gem::Version
40
40
  version: '3.2'
41
41
  description: Fast access to database results without the memory overhead of ActiveRecord
@@ -57,6 +57,8 @@ files:
57
57
  - ar-ondemand.gemspec
58
58
  - lib/ar-ondemand.rb
59
59
  - lib/ar-ondemand/delete_all_by_pk.rb
60
+ - lib/ar-ondemand/fast_enumeration.rb
61
+ - lib/ar-ondemand/for_enumeration_reading.rb
60
62
  - lib/ar-ondemand/for_reading.rb
61
63
  - lib/ar-ondemand/for_streaming.rb
62
64
  - lib/ar-ondemand/on_demand.rb
@@ -71,6 +73,7 @@ files:
71
73
  - spec/factories/audit_record.rb
72
74
  - spec/factories/widget.rb
73
75
  - spec/lib/delete_all_by_pk_spec.rb
76
+ - spec/lib/for_enumeration_reading_spec.rb
74
77
  - spec/lib/for_reading_spec.rb
75
78
  - spec/lib/for_streaming_spec.rb
76
79
  - spec/lib/on_demand_spec.rb