active_record_data_loader 0.1.2 → 1.0.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
  SHA256:
3
- metadata.gz: 43867d09da0479be24e9a23687d53cd4137f5ff8b47f769183a9bee19d6f8372
4
- data.tar.gz: 71ea6ea8d1cbc9821168a0f87e90c7e6e08f2b2053c48905bb0bcfe95f5d37f0
3
+ metadata.gz: 5c2971599904ef04249cbada28e924103f7a7f37e0d397e047502063bebd4297
4
+ data.tar.gz: 4b9d6471bb8c01937b459ca21cd8fcff18d2f13950102a63bebb13aa20584fb3
5
5
  SHA512:
6
- metadata.gz: 2523c1db84ecd726ba333369646a0fe1e9b6ee8e0e0dc5694e2b8a8ef693fe752c8685914d122c7d9561dd05ff3c1d1905a328445a7407c82596b72cf0f5e9ff
7
- data.tar.gz: 3c95553f3b39a535739e3fd998f67ca0c5420e37411d229b9284c0ccc99c9b7690d56a835b8fdaadfddc6f8750604f29852f77198b5a178c4cbab00bf3d80a1f
6
+ metadata.gz: c324c5783427ca9aacb88496e2b76669ade344fdb3d9eb4d640d2579cf9c472eee2a62367478d5211aead5572c155f4beb3ce12c5202503bb80e6f134a565743
7
+ data.tar.gz: f6f558c48d05973eed5cd9659b5204af780075ee19b8e046ddc1428385e1155a266cdacb052220b1b5354a5e7a50ea04e12c4eefac77002f2fa302bd772ec1e7
data/.travis.yml CHANGED
@@ -1,11 +1,23 @@
1
1
  sudo: false
2
2
  language: ruby
3
+ env:
4
+ - COVERALLS_PARALLEL=true
3
5
  rvm:
4
- - 2.4.3
6
+ - 2.3.8
7
+ - 2.4.6
8
+ - 2.5.5
9
+ - 2.6.3
10
+ gemfile:
11
+ - gemfiles/activerecord_5.gemfile
12
+ - gemfiles/rails.gemfile
13
+ - gemfiles/faker.gemfile
14
+ - gemfiles/ffaker.gemfile
5
15
  services:
6
16
  - postgresql
7
- before_install: gem install bundler -v 1.16.1
17
+ notifications:
18
+ webhooks: https://coveralls.io/webhook
19
+ before_install: "gem update --system && gem install bundler"
8
20
  before_script:
9
21
  - psql -c 'create database test;' -U postgres
10
22
  - cp config/database.yml.travis config/database.yml
11
- script: ./script/ci_build.sh
23
+ script: "bundle exec rake"
data/Appraisals CHANGED
@@ -4,6 +4,10 @@ appraise "activerecord-5" do
4
4
  gem "activerecord", "~> 5.0"
5
5
  end
6
6
 
7
+ appraise "rails" do
8
+ gem "rails"
9
+ end
10
+
7
11
  appraise "faker" do
8
12
  gem "faker", ">= 1.9.3"
9
13
  end
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- active_record_data_loader (0.1.2)
4
+ active_record_data_loader (1.0.0)
5
5
  activerecord (>= 4.0)
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -1,6 +1,5 @@
1
1
  # ActiveRecord Data Loader
2
2
 
3
- [![Gem Version](https://badge.fury.io/rb/active_record_data_loader.svg)](https://badge.fury.io/rb/active_record_data_loader)
4
3
  [![Build Status](https://travis-ci.org/abeiderman/active_record_data_loader.svg?branch=master)](https://travis-ci.org/abeiderman/active_record_data_loader)
5
4
  [![Coverage Status](https://coveralls.io/repos/github/abeiderman/active_record_data_loader/badge.svg?branch=master&service=github)](https://coveralls.io/github/abeiderman/active_record_data_loader?branch=master)
6
5
  [![Maintainability](https://api.codeclimate.com/v1/badges/338904b3f7e8d19a3cb1/maintainability)](https://codeclimate.com/github/abeiderman/active_record_data_loader/maintainability)
@@ -29,7 +28,181 @@ Or install it yourself as:
29
28
 
30
29
  ## Usage
31
30
 
32
- TODO: Write usage instructions here
31
+ The gem will recognize most commonly used column types and attempt to populate with sensible values by default. You can override this behavior as you will see further below.
32
+
33
+ `belongs_to` associations are recognized automatically. However, data is loaded in the order you define, so you want to make sure the parent model is loaded first.
34
+
35
+ Polymorphic associations need to be defined explicitly as shown in [Polymorphic associations](#polymorphic-associations).
36
+
37
+ ### Basic usage
38
+
39
+ Let's say you have the following models:
40
+ ```ruby
41
+ class Customer < ApplicationRecord
42
+ end
43
+
44
+ class Order < ApplicationRecord
45
+ belongs_to :customer
46
+ end
47
+ ```
48
+
49
+ The following code will create 10,000 customers and 100,000 orders, and will associate the orders to those customers evenly:
50
+ ```ruby
51
+ data_loader = ActiveRecordDataLoader.define do
52
+ model Customer do |m|
53
+ m.count 10_000
54
+ end
55
+
56
+ model Order do |m|
57
+ m.count 100_000
58
+ end
59
+ end
60
+
61
+ data_loader.load_data
62
+ ```
63
+
64
+ #### Overriding column values
65
+ To provide your own values for columns your can provide a lambda or a constant value:
66
+ ```ruby
67
+ data_loader = ActiveRecordDataLoader.define do
68
+ model Customer do |m|
69
+ m.count 10_000
70
+ m.column :name, -> { %w[Jane John Mary Matt].sample }
71
+ m.column :country, "USA"
72
+ m.column :terminated_at, nil
73
+ end
74
+
75
+ ...
76
+ end
77
+
78
+ data_loader.load_data
79
+ ```
80
+
81
+ ### Controlling associations
82
+ Let's say that you have certain restrictions on orders depending on country. You would want to test data to follow those restrictions which means orders cannot be randomly associated to any customer. You can control that by providing an `eligible_set` on the association.
83
+
84
+ In this example, we are creating 25K orders for customers in CAN with a CAD currency, 25K for customers in MEX with a MXN currency, and 50K for those in USA with a USD currency.
85
+
86
+ ```ruby
87
+ data_loader = ActiveRecordDataLoader.define do
88
+ model Customer do |m|
89
+ m.count 10_000
90
+ m.column :country, -> { %w[CAN MXN USA].sample }
91
+ end
92
+
93
+ model Order do |m|
94
+ m.count 25_000
95
+ m.column :currency, "CAD"
96
+ m.belongs_to :customer, eligible_set: -> { Customer.where(country: "CAN") }
97
+ end
98
+
99
+ model Order do |m|
100
+ m.count 25_000
101
+ m.column :currency, "MXN"
102
+ m.belongs_to :customer, eligible_set: -> { Customer.where(country: "MEX") }
103
+ end
104
+
105
+ model Order do |m|
106
+ m.count 50_000
107
+ m.column :currency, "USD"
108
+ m.belongs_to :customer, eligible_set: -> { Customer.where(country: "USA") }
109
+ end
110
+ end
111
+
112
+ data_loader.load_data
113
+ ```
114
+
115
+ ### Polymorphic associations
116
+
117
+ If you have a polymorphic `belongs_to` association, you will need to define that explicitly for it to be populated.
118
+
119
+ Let's assume the following models where an order could belong to either a person or a business:
120
+ ```ruby
121
+ class Person < ApplicationRecord
122
+ has_many :orders
123
+ end
124
+
125
+ class Business < ApplicationRecord
126
+ has_many :orders
127
+ end
128
+
129
+ class Order < ApplicationRecord
130
+ belongs_to :customer, polymorphic: true
131
+ end
132
+ ```
133
+
134
+ In order to populate the `customer` association in orders, you would specify them like this:
135
+ ```ruby
136
+ data_loader = ActiveRecordDataLoader.define do
137
+ model Person do |m|
138
+ m.count 5_000
139
+ end
140
+
141
+ model Business do |m|
142
+ m.count 5_000
143
+ end
144
+
145
+ model Order do |m|
146
+ m.count 100_000
147
+
148
+ m.polymorphic :customer do |c|
149
+ c.model Person
150
+ c.model Business
151
+ end
152
+ end
153
+ end
154
+
155
+ data_loader.load_data
156
+ ```
157
+
158
+ You can also provide a `weight` to each of the target models if you want to control how they are distributed. If you wanted to have twice as many orders for `Person` than for `Business`, it would look like this:
159
+ ```ruby
160
+ data_loader = ActiveRecordDataLoader.define do
161
+ model Person do |m|
162
+ m.count 5_000
163
+ end
164
+
165
+ model Business do |m|
166
+ m.count 5_000
167
+ end
168
+
169
+ model Order do |m|
170
+ m.count 100_000
171
+
172
+ m.polymorphic :customer do |c|
173
+ c.model Person, weight: 2
174
+ c.model Business, weight: 1
175
+ end
176
+ end
177
+ end
178
+
179
+ data_loader.load_data
180
+ ```
181
+
182
+ Additionaly, you can also provide an `eligible_set` to control which records to limit the association to:
183
+ ```ruby
184
+ data_loader = ActiveRecordDataLoader.define do
185
+ model Person do |m|
186
+ m.count 5_000
187
+ end
188
+
189
+ model Business do |m|
190
+ m.count 5_000
191
+ m.column :country, -> { %w[CAN USA].sample }
192
+ end
193
+
194
+ model Order do |m|
195
+ m.count 100_000
196
+
197
+ m.polymorphic :customer do |c|
198
+ c.model Person, weight: 2
199
+ c.model Business, weight: 1, eligible_set: -> { Business.where(country: "USA") }
200
+ end
201
+ end
202
+ end
203
+
204
+ data_loader.load_data
205
+ ```
33
206
 
34
207
  ## Development
35
208
 
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "rails"
6
+
7
+ gemspec path: "../"
@@ -38,12 +38,20 @@ module ActiveRecordDataLoader
38
38
  def possible_values
39
39
  @possible_values ||= begin
40
40
  values = @settings.models.keys.map do |klass|
41
- [klass.name, klass.all.pluck(klass.primary_key).to_a]
41
+ [klass.name, base_query(klass).pluck(klass.primary_key).to_a]
42
42
  end.to_h
43
43
 
44
44
  @settings.weighted_models.map { |klass| [klass.name, values[klass.name]] }
45
45
  end
46
46
  end
47
+
48
+ def base_query(klass)
49
+ if @settings.queries[klass]&.respond_to?(:call)
50
+ @settings.queries[klass].call.all
51
+ else
52
+ klass.all
53
+ end
54
+ end
47
55
  end
48
56
  end
49
57
  end
@@ -7,13 +7,23 @@ module ActiveRecordDataLoader
7
7
  def initialize(
8
8
  default_batch_size: 100_000,
9
9
  default_row_count: 1,
10
- logger: Logger.new(STDOUT, level: :info),
10
+ logger: nil,
11
11
  statement_timeout: "2min"
12
12
  )
13
13
  @default_batch_size = default_batch_size
14
14
  @default_row_count = default_row_count
15
- @logger = logger
15
+ @logger = logger || default_logger
16
16
  @statement_timeout = statement_timeout
17
17
  end
18
+
19
+ private
20
+
21
+ def default_logger
22
+ if defined?(Rails) && Rails.respond_to?(:logger)
23
+ Rails.logger
24
+ else
25
+ Logger.new(STDOUT, level: :info)
26
+ end
27
+ end
18
28
  end
19
29
  end
@@ -3,16 +3,18 @@
3
3
  module ActiveRecordDataLoader
4
4
  module Dsl
5
5
  class PolymorphicAssociation
6
- attr_reader :model_class, :name, :models
6
+ attr_reader :model_class, :name, :models, :queries
7
7
 
8
8
  def initialize(model_class, name)
9
9
  @model_class = model_class
10
10
  @name = name
11
11
  @models = {}
12
+ @queries = {}
12
13
  end
13
14
 
14
- def model(klass, weight: 1)
15
+ def model(klass, weight: 1, eligible_set: nil)
15
16
  @models[klass] = weight.to_i
17
+ @queries[klass] = eligible_set if eligible_set
16
18
  end
17
19
 
18
20
  def weighted_models
@@ -39,6 +39,7 @@ module ActiveRecordDataLoader
39
39
  batch_count = (total_rows / batch_size.to_f).ceil
40
40
 
41
41
  logger.info(
42
+ "[ActiveRecordDataLoader] "\
42
43
  "Loading #{total_rows} row(s) into '#{strategy.table_name}' via #{strategy.name}. "\
43
44
  "#{batch_size} row(s) per batch, #{batch_count} batch(es)."
44
45
  )
@@ -46,6 +47,7 @@ module ActiveRecordDataLoader
46
47
  load_in_batches(batch_size, total_rows, batch_count)
47
48
  end
48
49
  logger.info(
50
+ "[ActiveRecordDataLoader] "\
49
51
  "Completed loading #{total_rows} row(s) into '#{strategy.table_name}' "\
50
52
  "in #{total_time} seconds."
51
53
  )
@@ -61,6 +63,7 @@ module ActiveRecordDataLoader
61
63
  time = Benchmark.realtime { strategy.load_batch(row_numbers, connection) }
62
64
 
63
65
  logger.debug(
66
+ "[ActiveRecordDataLoader] "\
64
67
  "Completed batch #{i + 1}/#{batch_count}, #{row_numbers.count} row(s) in #{time} seconds"
65
68
  )
66
69
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveRecordDataLoader
4
- VERSION = "0.1.2"
4
+ VERSION = "1.0.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_record_data_loader
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alejandro Beiderman
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-06-11 00:00:00.000000000 Z
11
+ date: 2019-06-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -194,6 +194,7 @@ files:
194
194
  - gemfiles/activerecord_6.gemfile
195
195
  - gemfiles/faker.gemfile
196
196
  - gemfiles/ffaker.gemfile
197
+ - gemfiles/rails.gemfile
197
198
  - lib/active_record_data_loader.rb
198
199
  - lib/active_record_data_loader/active_record/belongs_to_configuration.rb
199
200
  - lib/active_record_data_loader/active_record/column_configuration.rb
@@ -213,7 +214,6 @@ files:
213
214
  - lib/active_record_data_loader/loader.rb
214
215
  - lib/active_record_data_loader/version.rb
215
216
  - log/.keep
216
- - script/ci_build.sh
217
217
  homepage:
218
218
  licenses:
219
219
  - MIT
data/script/ci_build.sh DELETED
@@ -1,4 +0,0 @@
1
- #! /bin/bash
2
- bundle exec appraisal
3
- bundle exec appraisal rake
4
- bundle exec rake coveralls:push