polo 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +35 -0
- data/README.md +26 -4
- data/lib/polo/collector.rb +18 -5
- data/lib/polo/configuration.rb +20 -3
- data/lib/polo/translator.rb +18 -5
- data/lib/polo/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 241a2fd317d2b766497c31f824c4a9c76309df49
|
4
|
+
data.tar.gz: cdfa23f93211a11f43414aba198b9edcf9e6203a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 63c36ebd40006d1f542474e86f4f91d343b1b99ab6b59054597f749274b3bdc919ea9ea2a5db8bfac2eafe46123030b55084ce2039767907b68555867acc3585
|
7
|
+
data.tar.gz: 4765c393aa6e1b19b784bcbc8d14dc22e3fcab1f8a7a048bb1dfdf01e3f269290a51957f271aead96e1fbedf24de87aab70949dd14018a010aa451932a97e4d6
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
## 0.2.0
|
2
|
+
|
3
|
+
### Breaking Changes
|
4
|
+
|
5
|
+
- None
|
6
|
+
|
7
|
+
### Added
|
8
|
+
|
9
|
+
- [#8](https://github.com/IFTTT/polo/pull/8) Global settings
|
10
|
+
- [#17](https://github.com/IFTTT/polo/pull/17) Using random generator instead of character shuffle for data obfuscation
|
11
|
+
- [#18](https://github.com/IFTTT/polo/pull/18) Add a CHANGELOG
|
12
|
+
- [#20](https://github.com/IFTTT/polo/pull/20) Postgres Support
|
13
|
+
|
14
|
+
### Fixed
|
15
|
+
|
16
|
+
- Typo fixes on the README: [#9](https://github.com/IFTTT/polo/pull/9), [#10](https://github.com/IFTTT/polo/pull/10)
|
17
|
+
- [#11]() Some ActiveRecord classes do not use id as the primary key
|
18
|
+
- [#25](https://github.com/IFTTT/polo/pull/25) Fix Custom Strategy
|
19
|
+
|
20
|
+
## 0.1.0
|
21
|
+
|
22
|
+
### Breaking Changes
|
23
|
+
|
24
|
+
- None
|
25
|
+
|
26
|
+
### Added
|
27
|
+
|
28
|
+
- [#2](https://github.com/IFTTT/polo/pull/2) Add :ignore and :override options to deal with data collision
|
29
|
+
- [#3](https://github.com/IFTTT/polo/pull/3) Add option to obfuscate fields
|
30
|
+
- [#4](https://github.com/IFTTT/polo/pull/4) Add intro to Update / Ignore section
|
31
|
+
- [#6](https://github.com/IFTTT/polo/pull/6) Set up Appraisal to run specs across Rails 3.2 through 4.2
|
32
|
+
|
33
|
+
### Fixed
|
34
|
+
|
35
|
+
- [#7](https://github.com/IFTTT/polo/pull/7) Fix casting of values
|
data/README.md
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
[![Open Source at IFTTT](http://ifttt.github.io/images/open-source-ifttt.svg)](http://ifttt.github.io)
|
2
|
+
[![Build Status](https://travis-ci.org/IFTTT/polo.svg?branch=master)](https://travis-ci.org/IFTTT/polo)
|
2
3
|
|
3
4
|
![Polo](https://raw.githubusercontent.com/IFTTT/polo/images/images/polo.png "Polo")
|
4
5
|
|
@@ -9,6 +10,9 @@ Polo takes an `ActiveRecord::Base` seed object and traverses every whitelisted `
|
|
9
10
|
|
10
11
|
You can then save those SQL `INSERTS` to .sql file and import the data to your favorite environment.
|
11
12
|
|
13
|
+
# Motivation
|
14
|
+
Read our [blog post](https://medium.com/engineering-at-ifttt/happier-rails-development-with-polo-9df6819136d3#.f8ll3azeq) or check out this [presentation](https://speakerdeck.com/nettofarah/polo-working-with-real-world-data-in-development).
|
15
|
+
|
12
16
|
## Usage
|
13
17
|
Given the following data model:
|
14
18
|
```ruby
|
@@ -74,7 +78,8 @@ INSERT INTO `ingredients` (`id`, `name`, `quantity`) VALUES (4, 'Cheese', '2 sli
|
|
74
78
|
|
75
79
|
Occasionally, you might have a dataset that you want to refresh. A production database that has data that might be useful on your local copy of the database. Polo doesn't have an opinion about your data; if you try to import data with a key that's already in your local database, Polo doesn't necessarily know how you want to handle that conflict.
|
76
80
|
|
77
|
-
Advanced users will find the `on_duplicate` option to be helpful in this context. It gives Polo instructions on how to handle collisions.
|
81
|
+
Advanced users will find the `on_duplicate` option to be helpful in this context. It gives Polo instructions on how to handle collisions.
|
82
|
+
*Note: This feature is currently only supported for MySQL databases. (PRs for other databases are welcome!)*
|
78
83
|
|
79
84
|
There are two possible values for the `on_duplicate` key: `:ignore` and `:override`. Ignore keeps the old data. Override keeps the new data. If there's a collision and the on_duplicate param is not set, Polo will simpy stop importing the data.
|
80
85
|
|
@@ -128,9 +133,26 @@ Polo::Traveler.explore(AR::Chef, 1)
|
|
128
133
|
INSERT INTO `chefs` (`id`, `name`, `email`) VALUES (1, 'Netto', 'eahorctmaagfo.nitm@l')
|
129
134
|
```
|
130
135
|
|
131
|
-
Warning: This is not a security feature. Fields can still easily be rearranged back to their original format. Polo will simply scramble the order of strings so you don't
|
136
|
+
Warning: This is not a security feature. Fields can still easily be rearranged back to their original format. Polo will simply scramble the order of strings so you don't accidentally end up causing side effects when using production data in development. It is not a good practice to use highly sensitive data in development.
|
137
|
+
|
138
|
+
#### Advanced Obfuscation
|
139
|
+
|
140
|
+
For more advanced obfuscation, you can pass in a custom obfuscation strategy.
|
141
|
+
Polo will take in a lambda that can be used to transform sensitive data.
|
142
|
+
|
143
|
+
````ruby
|
144
|
+
Polo.configure do
|
145
|
+
email_strategy = lambda {|e| "#{e.split("@")[0]}_test@example.com" }
|
146
|
+
credit_card_strategy = lambda {|_| "4111111111111111"}
|
147
|
+
obfuscate({email: email_strategy, credit_card: credit_card_strategy})
|
148
|
+
end
|
149
|
+
|
150
|
+
Polo::Traveler.explore(AR::Chef, 1)
|
151
|
+
````
|
132
152
|
|
133
|
-
|
153
|
+
```sql
|
154
|
+
INSERT INTO `chefs` (`id`, `name`, `email`) VALUES (1, 'Netto', 'netto_test.@example.com')
|
155
|
+
```
|
134
156
|
|
135
157
|
## Installation
|
136
158
|
|
@@ -152,7 +174,7 @@ $ gem install polo
|
|
152
174
|
|
153
175
|
## Contributing
|
154
176
|
|
155
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
177
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/IFTTT/polo. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](contributor-covenant.org) code of conduct.
|
156
178
|
|
157
179
|
To run the specs across all supported version of Rails, check out the repo and
|
158
180
|
follow these steps:
|
data/lib/polo/collector.rb
CHANGED
@@ -14,10 +14,12 @@ module Polo
|
|
14
14
|
# ActiveSupport::Notifications block and collecting every generate SQL query.
|
15
15
|
#
|
16
16
|
def collect
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
17
|
+
unprepared_statement do
|
18
|
+
ActiveSupport::Notifications.subscribed(collector, 'sql.active_record') do
|
19
|
+
base_finder = @base_class.includes(@dependency_tree).where(@base_class.primary_key => @id)
|
20
|
+
collect_sql(@base_class, base_finder.to_sql)
|
21
|
+
base_finder.to_a
|
22
|
+
end
|
21
23
|
end
|
22
24
|
|
23
25
|
@selects.compact.uniq
|
@@ -33,8 +35,9 @@ module Polo
|
|
33
35
|
#
|
34
36
|
def collector
|
35
37
|
lambda do |name, start, finish, id, payload|
|
38
|
+
return unless payload[:name] =~ /^(.*) Load$/
|
36
39
|
begin
|
37
|
-
class_name =
|
40
|
+
class_name = $1.constantize
|
38
41
|
sql = payload[:sql]
|
39
42
|
collect_sql(class_name, sql)
|
40
43
|
rescue ActiveRecord::StatementInvalid, NameError
|
@@ -49,5 +52,15 @@ module Polo
|
|
49
52
|
sql: sql
|
50
53
|
}
|
51
54
|
end
|
55
|
+
|
56
|
+
def unprepared_statement
|
57
|
+
if ActiveRecord::Base.connection.respond_to?(:unprepared_statement)
|
58
|
+
ActiveRecord::Base.connection.unprepared_statement do
|
59
|
+
yield
|
60
|
+
end
|
61
|
+
else
|
62
|
+
yield
|
63
|
+
end
|
64
|
+
end
|
52
65
|
end
|
53
66
|
end
|
data/lib/polo/configuration.rb
CHANGED
@@ -4,13 +4,30 @@ module Polo
|
|
4
4
|
attr_reader :on_duplicate_strategy, :blacklist
|
5
5
|
|
6
6
|
def initialize(options={})
|
7
|
-
options = { on_duplicate: nil, obfuscate:
|
7
|
+
options = { on_duplicate: nil, obfuscate: {} }.merge(options)
|
8
8
|
@on_duplicate_strategy = options[:on_duplicate]
|
9
|
-
|
9
|
+
obfuscate(options[:obfuscate])
|
10
10
|
end
|
11
11
|
|
12
|
+
# TODO: document this
|
13
|
+
# This normalizes an array or hash of fields to a hash of
|
14
|
+
# { field_name => strategy }
|
12
15
|
def obfuscate(*fields)
|
13
|
-
|
16
|
+
if fields.is_a?(Array)
|
17
|
+
fields = fields.flatten
|
18
|
+
end
|
19
|
+
|
20
|
+
fields_and_strategies = {}
|
21
|
+
|
22
|
+
fields.each do |field|
|
23
|
+
if field.is_a?(Symbol) || field.is_a?(String)
|
24
|
+
fields_and_strategies[field] = nil
|
25
|
+
elsif field.is_a?(Hash)
|
26
|
+
fields_and_strategies = fields_and_strategies.merge(field)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
@blacklist = fields_and_strategies
|
14
31
|
end
|
15
32
|
|
16
33
|
def on_duplicate(strategy)
|
data/lib/polo/translator.rb
CHANGED
@@ -25,7 +25,7 @@ module Polo
|
|
25
25
|
end
|
26
26
|
|
27
27
|
if fields = @configuration.blacklist
|
28
|
-
obfuscate!(active_record_instances, fields
|
28
|
+
obfuscate!(active_record_instances, fields)
|
29
29
|
end
|
30
30
|
|
31
31
|
active_record_instances
|
@@ -35,12 +35,25 @@ module Polo
|
|
35
35
|
|
36
36
|
def obfuscate!(instances, fields)
|
37
37
|
instances.each do |instance|
|
38
|
-
next if (instance.attributes.keys
|
39
|
-
|
40
|
-
|
41
|
-
instance.
|
38
|
+
next if intersection(instance.attributes.keys, fields).empty?
|
39
|
+
|
40
|
+
fields.each do |field, strategy|
|
41
|
+
value = instance.attributes[field.to_s] || ''
|
42
|
+
instance.send("#{field}=", new_field_value(field, strategy, value))
|
42
43
|
end
|
43
44
|
end
|
44
45
|
end
|
46
|
+
|
47
|
+
def intersection(attrs, fields)
|
48
|
+
attrs & fields.keys.map(&:to_s)
|
49
|
+
end
|
50
|
+
|
51
|
+
def new_field_value(field, strategy, value)
|
52
|
+
if strategy.nil?
|
53
|
+
value.split("").shuffle.join
|
54
|
+
else
|
55
|
+
strategy.call(value)
|
56
|
+
end
|
57
|
+
end
|
45
58
|
end
|
46
59
|
end
|
data/lib/polo/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: polo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Netto Farah
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-12-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -107,6 +107,7 @@ files:
|
|
107
107
|
- ".ruby-version"
|
108
108
|
- ".travis.yml"
|
109
109
|
- Appraisals
|
110
|
+
- CHANGELOG.md
|
110
111
|
- CODE_OF_CONDUCT.md
|
111
112
|
- Gemfile
|
112
113
|
- LICENSE.txt
|