polo 0.2.0 → 0.3.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: 241a2fd317d2b766497c31f824c4a9c76309df49
4
- data.tar.gz: cdfa23f93211a11f43414aba198b9edcf9e6203a
3
+ metadata.gz: d3f754e19121b0fb417f692c5ee333daeb8de049
4
+ data.tar.gz: 326da5077810478da02f66de52e749cac05866cc
5
5
  SHA512:
6
- metadata.gz: 63c36ebd40006d1f542474e86f4f91d343b1b99ab6b59054597f749274b3bdc919ea9ea2a5db8bfac2eafe46123030b55084ce2039767907b68555867acc3585
7
- data.tar.gz: 4765c393aa6e1b19b784bcbc8d14dc22e3fcab1f8a7a048bb1dfdf01e3f269290a51957f271aead96e1fbedf24de87aab70949dd14018a010aa451932a97e4d6
6
+ metadata.gz: 453c79f229642062534266178aabc162bbfdf06231c2b0237c828ef9277cc96c9987a9471096664a06c16b313f058c95f68e194bdd824a79ec01f232ad3a55f1
7
+ data.tar.gz: bfa5e063eb14430036621742fb3bc72e5159cf307a3efbd2e09894fb93c95c5face35766e8e78a7496ae9d2c7f05349796c021cd5452319271af0a688ea2a5a5
data/.gitignore CHANGED
@@ -7,3 +7,4 @@
7
7
  /pkg/
8
8
  /spec/reports/
9
9
  /tmp/
10
+ /gemfiles/*.gemfile.lock
data/.rspec CHANGED
File without changes
@@ -1 +1 @@
1
- 2.1.5
1
+ 2.2.1
@@ -6,4 +6,4 @@ gemfile:
6
6
  - gemfiles/rails40.gemfile
7
7
  - gemfiles/rails41.gemfile
8
8
  - gemfiles/rails42.gemfile
9
- before_install: gem install bundler -v 1.10.6
9
+ before_install: gem install bundler -v 1.11.2
data/Appraisals CHANGED
File without changes
@@ -1,3 +1,22 @@
1
+ ## 0.3.0
2
+
3
+ ### Breaking Changes
4
+
5
+ - None
6
+
7
+ ### Added
8
+
9
+ - [#30](https://github.com/IFTTT/polo/pull/30) Advanced obfuscation
10
+ - [#37](https://github.com/IFTTT/polo/pull/37) Custom adapters for Postgres and MySQL
11
+
12
+ ### Fixed
13
+
14
+ - [#26](https://github.com/IFTTT/polo/pull/26) Postgres - Use ActiveRecord methods to generate INSERT SQLs
15
+ - [#25](https://github.com/IFTTT/polo/pull/25) Fix custom strategies bug
16
+ - [#28](https://github.com/IFTTT/polo/pull/28) Only obfuscate fields when they are present
17
+ - [#35](https://github.com/IFTTT/polo/pull/35) Better support for Rails 4.0
18
+ - [#31](https://github.com/IFTTT/polo/pull/31) Fix link to Code of Conduct
19
+
1
20
  ## 0.2.0
2
21
 
3
22
  ### Breaking Changes
File without changes
data/Gemfile CHANGED
File without changes
File without changes
data/README.md CHANGED
@@ -10,7 +10,7 @@ Polo takes an `ActiveRecord::Base` seed object and traverses every whitelisted `
10
10
 
11
11
  You can then save those SQL `INSERTS` to .sql file and import the data to your favorite environment.
12
12
 
13
- # Motivation
13
+ ## Motivation
14
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
15
 
16
16
  ## Usage
@@ -137,14 +137,26 @@ Warning: This is not a security feature. Fields can still easily be rearranged b
137
137
 
138
138
  #### Advanced Obfuscation
139
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.
140
+ For more advanced obfuscation, you can pass in a custom obfuscation strategy. Polo will take in a lambda that can be used to transform sensitive data.
141
+
142
+ Using a `:symbol` as an obfuscate key targets all columns of that name. Passing an SQL selector as a `String` will target columns within the specified table.
142
143
 
143
144
  ````ruby
144
145
  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})
146
+
147
+ email_strategy = lambda do |email|
148
+ first_part = email.split("@")[0]
149
+ "#{first_part}@test.com"
150
+ end
151
+
152
+ credit_card_strategy = lambda do |credit_card|
153
+ "4123 4567 8910 1112"
154
+ end
155
+
156
+ obfuscate({
157
+ 'chefs.email' => email_strategy, # This only applies to the "email" column in the "chefs" table
158
+ :credit_card => credit_card_strategy # This applies to any column named "credit_card" across every table
159
+ })
148
160
  end
149
161
 
150
162
  Polo::Traveler.explore(AR::Chef, 1)
@@ -174,7 +186,7 @@ $ gem install polo
174
186
 
175
187
  ## Contributing
176
188
 
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.
189
+ 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 [Code of Conduct](https://github.com/IFTTT/polo/blob/master/CODE_OF_CONDUCT.md).
178
190
 
179
191
  To run the specs across all supported version of Rails, check out the repo and
180
192
  follow these steps:
data/Rakefile CHANGED
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,24 @@
1
+ module Polo
2
+ module Adapters
3
+ class MySQL
4
+ def on_duplicate_key_update(inserts, records)
5
+ insert_and_record = inserts.zip(records)
6
+ insert_and_record.map do |insert, record|
7
+ values_syntax = record.attributes.keys.map do |key|
8
+ "#{key} = VALUES(#{key})"
9
+ end
10
+
11
+ on_dup_syntax = "ON DUPLICATE KEY UPDATE #{values_syntax.join(', ')}"
12
+
13
+ "#{insert} #{on_dup_syntax}"
14
+ end
15
+ end
16
+
17
+ def ignore_transform(inserts, records)
18
+ inserts.map do |insert|
19
+ insert.gsub("INSERT", "INSERT IGNORE")
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,32 @@
1
+ module Polo
2
+ module Adapters
3
+ class Postgres
4
+ # TODO: Implement UPSERT. This command became available in 9.1.
5
+ #
6
+ # See: http://www.the-art-of-web.com/sql/upsert/
7
+ def on_duplicate_key_update(inserts, records)
8
+ raise 'on_duplicate: :override is not currently supported in the PostgreSQL adapter'
9
+ end
10
+
11
+ # Internal: Transforms an INSERT with PostgreSQL-specific syntax. Ignores
12
+ # records that alread exist in the table. To do this, it uses
13
+ # a heuristic, i.e. checks if there is a record with the same id
14
+ # in the table.
15
+ # See: http://stackoverflow.com/a/6527838/32816
16
+ #
17
+ # inserts - The Array of INSERT statements.
18
+ # records - The Array of Arel objects.
19
+ #
20
+ # Returns the Array of transformed INSERT statements.
21
+ def ignore_transform(inserts, records)
22
+ insert_and_record = inserts.zip(records)
23
+ insert_and_record.map do |insert, record|
24
+ table_name = record.class.arel_table.name
25
+ id = record[:id]
26
+ insert = insert.gsub(/VALUES \((.+)\)$/m, 'SELECT \\1')
27
+ insert << " WHERE NOT EXISTS (SELECT 1 FROM #{table_name} WHERE id=#{id});"
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
File without changes
@@ -1,10 +1,11 @@
1
1
  module Polo
2
2
 
3
3
  class Configuration
4
- attr_reader :on_duplicate_strategy, :blacklist
4
+ attr_reader :on_duplicate_strategy, :blacklist, :adapter
5
5
 
6
6
  def initialize(options={})
7
- options = { on_duplicate: nil, obfuscate: {} }.merge(options)
7
+ options = { on_duplicate: nil, obfuscate: {}, adapter: :mysql }.merge(options)
8
+ @adapter = options[:adapter]
8
9
  @on_duplicate_strategy = options[:on_duplicate]
9
10
  obfuscate(options[:obfuscate])
10
11
  end
@@ -33,5 +34,9 @@ module Polo
33
34
  def on_duplicate(strategy)
34
35
  @on_duplicate_strategy = strategy
35
36
  end
37
+
38
+ def set_adapter(db)
39
+ @adapter = db
40
+ end
36
41
  end
37
42
  end
@@ -1,93 +1,89 @@
1
1
  require 'active_record'
2
2
  require 'polo/configuration'
3
+ require 'polo/adapters/mysql'
4
+ require 'polo/adapters/postgres'
3
5
 
4
6
  module Polo
5
7
  class SqlTranslator
6
8
 
7
- def initialize(object, configuration=Configuration.new)
9
+ def initialize(object, configuration = Configuration.new)
8
10
  @record = object
9
11
  @configuration = configuration
10
- end
11
-
12
- def to_sql
13
- records = Array.wrap(@record)
14
12
 
15
- sqls = records.map do |record|
16
- raw_sql(record)
13
+ case @configuration.adapter
14
+ when :mysql
15
+ @adapter = Polo::Adapters::MySQL.new
16
+ when :postgres
17
+ @adapter = Polo::Adapters::Postgres.new
18
+ else
19
+ raise "Unknown SQL adapter: #{@configuration.adapter}"
17
20
  end
18
-
19
- if @configuration.on_duplicate_strategy == :ignore
20
- sqls = ignore_transform(sqls)
21
- end
22
-
23
- if @configuration.on_duplicate_strategy == :override
24
- sqls = on_duplicate_key_update(sqls, records)
25
- end
26
-
27
- sqls
28
21
  end
29
22
 
30
- private
31
-
32
- def on_duplicate_key_update(sqls, records)
33
- insert_and_record = sqls.zip(records)
34
- insert_and_record.map do |insert, record|
35
- values_syntax = record.attributes.keys.map do |key|
36
- "#{key} = VALUES(#{key})"
37
- end
38
-
39
- on_dup_syntax = "ON DUPLICATE KEY UPDATE #{values_syntax.join(', ')}"
40
-
41
- "#{insert} #{on_dup_syntax}"
23
+ def to_sql
24
+ case @configuration.on_duplicate_strategy
25
+ when :ignore
26
+ @adapter.ignore_transform(inserts, records)
27
+ when :override
28
+ @adapter.on_duplicate_key_update(inserts, records)
29
+ else inserts
42
30
  end
43
31
  end
44
32
 
45
- def ignore_transform(inserts)
46
- inserts.map do |insert|
47
- insert.gsub("INSERT", "INSERT IGNORE")
48
- end
33
+ def records
34
+ Array.wrap(@record)
49
35
  end
50
36
 
51
- def raw_sql(record)
52
- connection = ActiveRecord::Base.connection
53
- attributes = record.attributes
54
-
55
- keys = attributes.keys.map do |key|
56
- "`#{key}`"
37
+ def inserts
38
+ records.map do |record|
39
+ raw_sql(record)
57
40
  end
41
+ end
58
42
 
59
- values = attributes.map do |key, value|
60
- column = record.column_for_attribute(key)
61
- connection.quote(cast_attribute(record, column, value))
62
- end
43
+ private
63
44
 
64
- "INSERT INTO `#{record.class.table_name}` (#{keys.join(', ')}) VALUES (#{values.join(', ')})"
45
+ # Internal: Generates an insert SQL statement for a given record
46
+ #
47
+ # It will make use of the InsertManager class from the Arel gem to generate
48
+ # insert statements
49
+ #
50
+ def raw_sql(record)
51
+ record.class.arel_table.create_insert.tap do |insert_manager|
52
+ insert_manager.insert(insert_values(record))
53
+ end.to_sql
65
54
  end
66
55
 
67
- module ActiveRecordLessThanFourPointTwo
68
- def cast_attribute(record, column, value)
69
- attribute = record.send(:type_cast_attribute_for_write, column, value)
70
-
71
- if record.class.serialized_attributes.include?(column.name)
72
- attribute.serialize
73
- else
74
- attribute
75
- end
56
+ # Internal: Returns an object's attribute definitions along with
57
+ # their set values (for Rails 3.x).
58
+ #
59
+ module ActiveRecordLessThanFour
60
+ def insert_values(record)
61
+ record.send(:arel_attributes_values)
76
62
  end
77
63
  end
78
64
 
79
- module ActiveRecordFourPointTwoOrGreater
80
- def cast_attribute(record, column, value)
81
- column.type_cast_for_database(value)
65
+ # Internal: Returns an object's attribute definitions along with
66
+ # their set values (for Rails >= 4.x).
67
+ #
68
+ # From Rails 4.2 onwards, for some reason attributes with custom serializers
69
+ # wouldn't be properly serialized automatically. That's why explict
70
+ # 'type_cast' call are necessary.
71
+ #
72
+ module ActiveRecordFourOrGreater
73
+ def insert_values(record)
74
+ connection = ActiveRecord::Base.connection
75
+ values = record.send(:arel_attributes_with_values_for_create, record.attribute_names)
76
+ values.each do |attribute, value|
77
+ column = record.send(:column_for_attribute, attribute.name)
78
+ values[attribute] = connection.type_cast(value, column)
79
+ end
82
80
  end
83
81
  end
84
82
 
85
- if ActiveRecord::VERSION::STRING.start_with?('3.2') ||
86
- ActiveRecord::VERSION::STRING.start_with?('4.0') ||
87
- ActiveRecord::VERSION::STRING.start_with?('4.1')
88
- include ActiveRecordLessThanFourPointTwo
83
+ if ActiveRecord::VERSION::MAJOR < 4
84
+ include ActiveRecordLessThanFour
89
85
  else
90
- include ActiveRecordFourPointTwoOrGreater
86
+ include ActiveRecordFourOrGreater
91
87
  end
92
88
  end
93
89
  end
@@ -38,14 +38,31 @@ module Polo
38
38
  next if intersection(instance.attributes.keys, fields).empty?
39
39
 
40
40
  fields.each do |field, strategy|
41
- value = instance.attributes[field.to_s] || ''
42
- instance.send("#{field}=", new_field_value(field, strategy, value))
41
+ field = field.to_s
42
+
43
+ if table = table_name(field)
44
+ field = field_name(field)
45
+ end
46
+
47
+ correct_table = table.nil? || instance.class.table_name == table
48
+
49
+ if correct_table && value = instance.attributes[field]
50
+ instance.send("#{field}=", new_field_value(field, strategy, value))
51
+ end
43
52
  end
44
53
  end
45
54
  end
46
55
 
56
+ def field_name(field)
57
+ field.to_s.include?('.') ? field.split('.').last : field.to_s
58
+ end
59
+
60
+ def table_name(field)
61
+ field.to_s.include?('.') ? field.split('.').first : nil
62
+ end
63
+
47
64
  def intersection(attrs, fields)
48
- attrs & fields.keys.map(&:to_s)
65
+ attrs & fields.map { |pair| field_name(pair.first) }
49
66
  end
50
67
 
51
68
  def new_field_value(field, strategy, value)
@@ -1,3 +1,3 @@
1
1
  module Polo
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0"
3
3
  end
File without changes
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.2.0
4
+ version: 0.3.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-12-04 00:00:00.000000000 Z
11
+ date: 2016-04-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -114,14 +114,12 @@ files:
114
114
  - README.md
115
115
  - Rakefile
116
116
  - gemfiles/rails32.gemfile
117
- - gemfiles/rails32.gemfile.lock
118
117
  - gemfiles/rails40.gemfile
119
- - gemfiles/rails40.gemfile.lock
120
118
  - gemfiles/rails41.gemfile
121
- - gemfiles/rails41.gemfile.lock
122
119
  - gemfiles/rails42.gemfile
123
- - gemfiles/rails42.gemfile.lock
124
120
  - lib/polo.rb
121
+ - lib/polo/adapters/mysql.rb
122
+ - lib/polo/adapters/postgres.rb
125
123
  - lib/polo/collector.rb
126
124
  - lib/polo/configuration.rb
127
125
  - lib/polo/sql_translator.rb
@@ -1,61 +0,0 @@
1
- PATH
2
- remote: ../
3
- specs:
4
- polo (0.1.0)
5
- activerecord (>= 3.2)
6
-
7
- GEM
8
- remote: https://rubygems.org/
9
- specs:
10
- activemodel (3.2.22)
11
- activesupport (= 3.2.22)
12
- builder (~> 3.0.0)
13
- activerecord (3.2.22)
14
- activemodel (= 3.2.22)
15
- activesupport (= 3.2.22)
16
- arel (~> 3.0.2)
17
- tzinfo (~> 0.3.29)
18
- activesupport (3.2.22)
19
- i18n (~> 0.6, >= 0.6.4)
20
- multi_json (~> 1.0)
21
- appraisal (2.1.0)
22
- bundler
23
- rake
24
- thor (>= 0.14.0)
25
- arel (3.0.3)
26
- builder (3.0.4)
27
- diff-lcs (1.2.5)
28
- i18n (0.7.0)
29
- multi_json (1.11.2)
30
- rake (10.4.2)
31
- rspec (3.3.0)
32
- rspec-core (~> 3.3.0)
33
- rspec-expectations (~> 3.3.0)
34
- rspec-mocks (~> 3.3.0)
35
- rspec-core (3.3.2)
36
- rspec-support (~> 3.3.0)
37
- rspec-expectations (3.3.1)
38
- diff-lcs (>= 1.2.0, < 2.0)
39
- rspec-support (~> 3.3.0)
40
- rspec-mocks (3.3.2)
41
- diff-lcs (>= 1.2.0, < 2.0)
42
- rspec-support (~> 3.3.0)
43
- rspec-support (3.3.0)
44
- sqlite3 (1.3.10)
45
- thor (0.19.1)
46
- tzinfo (0.3.44)
47
-
48
- PLATFORMS
49
- ruby
50
-
51
- DEPENDENCIES
52
- activerecord (= 3.2.22)
53
- appraisal
54
- bundler (~> 1.10)
55
- polo!
56
- rake (~> 10.0)
57
- rspec
58
- sqlite3 (= 1.3.10)
59
-
60
- BUNDLED WITH
61
- 1.10.6
@@ -1,67 +0,0 @@
1
- PATH
2
- remote: ../
3
- specs:
4
- polo (0.1.0)
5
- activerecord (>= 3.2)
6
-
7
- GEM
8
- remote: https://rubygems.org/
9
- specs:
10
- activemodel (4.0.13)
11
- activesupport (= 4.0.13)
12
- builder (~> 3.1.0)
13
- activerecord (4.0.13)
14
- activemodel (= 4.0.13)
15
- activerecord-deprecated_finders (~> 1.0.2)
16
- activesupport (= 4.0.13)
17
- arel (~> 4.0.0)
18
- activerecord-deprecated_finders (1.0.4)
19
- activesupport (4.0.13)
20
- i18n (~> 0.6, >= 0.6.9)
21
- minitest (~> 4.2)
22
- multi_json (~> 1.3)
23
- thread_safe (~> 0.1)
24
- tzinfo (~> 0.3.37)
25
- appraisal (2.1.0)
26
- bundler
27
- rake
28
- thor (>= 0.14.0)
29
- arel (4.0.2)
30
- builder (3.1.4)
31
- diff-lcs (1.2.5)
32
- i18n (0.7.0)
33
- minitest (4.7.5)
34
- multi_json (1.11.2)
35
- rake (10.4.2)
36
- rspec (3.3.0)
37
- rspec-core (~> 3.3.0)
38
- rspec-expectations (~> 3.3.0)
39
- rspec-mocks (~> 3.3.0)
40
- rspec-core (3.3.2)
41
- rspec-support (~> 3.3.0)
42
- rspec-expectations (3.3.1)
43
- diff-lcs (>= 1.2.0, < 2.0)
44
- rspec-support (~> 3.3.0)
45
- rspec-mocks (3.3.2)
46
- diff-lcs (>= 1.2.0, < 2.0)
47
- rspec-support (~> 3.3.0)
48
- rspec-support (3.3.0)
49
- sqlite3 (1.3.10)
50
- thor (0.19.1)
51
- thread_safe (0.3.5)
52
- tzinfo (0.3.44)
53
-
54
- PLATFORMS
55
- ruby
56
-
57
- DEPENDENCIES
58
- activerecord (= 4.0.13)
59
- appraisal
60
- bundler (~> 1.10)
61
- polo!
62
- rake (~> 10.0)
63
- rspec
64
- sqlite3 (= 1.3.10)
65
-
66
- BUNDLED WITH
67
- 1.10.6
@@ -1,66 +0,0 @@
1
- PATH
2
- remote: ../
3
- specs:
4
- polo (0.1.0)
5
- activerecord (>= 3.2)
6
-
7
- GEM
8
- remote: https://rubygems.org/
9
- specs:
10
- activemodel (4.1.12)
11
- activesupport (= 4.1.12)
12
- builder (~> 3.1)
13
- activerecord (4.1.12)
14
- activemodel (= 4.1.12)
15
- activesupport (= 4.1.12)
16
- arel (~> 5.0.0)
17
- activesupport (4.1.12)
18
- i18n (~> 0.6, >= 0.6.9)
19
- json (~> 1.7, >= 1.7.7)
20
- minitest (~> 5.1)
21
- thread_safe (~> 0.1)
22
- tzinfo (~> 1.1)
23
- appraisal (2.1.0)
24
- bundler
25
- rake
26
- thor (>= 0.14.0)
27
- arel (5.0.1.20140414130214)
28
- builder (3.2.2)
29
- diff-lcs (1.2.5)
30
- i18n (0.7.0)
31
- json (1.8.3)
32
- minitest (5.8.0)
33
- rake (10.4.2)
34
- rspec (3.3.0)
35
- rspec-core (~> 3.3.0)
36
- rspec-expectations (~> 3.3.0)
37
- rspec-mocks (~> 3.3.0)
38
- rspec-core (3.3.2)
39
- rspec-support (~> 3.3.0)
40
- rspec-expectations (3.3.1)
41
- diff-lcs (>= 1.2.0, < 2.0)
42
- rspec-support (~> 3.3.0)
43
- rspec-mocks (3.3.2)
44
- diff-lcs (>= 1.2.0, < 2.0)
45
- rspec-support (~> 3.3.0)
46
- rspec-support (3.3.0)
47
- sqlite3 (1.3.10)
48
- thor (0.19.1)
49
- thread_safe (0.3.5)
50
- tzinfo (1.2.2)
51
- thread_safe (~> 0.1)
52
-
53
- PLATFORMS
54
- ruby
55
-
56
- DEPENDENCIES
57
- activerecord (= 4.1.12)
58
- appraisal
59
- bundler (~> 1.10)
60
- polo!
61
- rake (~> 10.0)
62
- rspec
63
- sqlite3 (= 1.3.10)
64
-
65
- BUNDLED WITH
66
- 1.10.6
@@ -1,66 +0,0 @@
1
- PATH
2
- remote: ../
3
- specs:
4
- polo (0.1.0)
5
- activerecord (>= 3.2)
6
-
7
- GEM
8
- remote: https://rubygems.org/
9
- specs:
10
- activemodel (4.2.3)
11
- activesupport (= 4.2.3)
12
- builder (~> 3.1)
13
- activerecord (4.2.3)
14
- activemodel (= 4.2.3)
15
- activesupport (= 4.2.3)
16
- arel (~> 6.0)
17
- activesupport (4.2.3)
18
- i18n (~> 0.7)
19
- json (~> 1.7, >= 1.7.7)
20
- minitest (~> 5.1)
21
- thread_safe (~> 0.3, >= 0.3.4)
22
- tzinfo (~> 1.1)
23
- appraisal (2.1.0)
24
- bundler
25
- rake
26
- thor (>= 0.14.0)
27
- arel (6.0.3)
28
- builder (3.2.2)
29
- diff-lcs (1.2.5)
30
- i18n (0.7.0)
31
- json (1.8.3)
32
- minitest (5.8.0)
33
- rake (10.4.2)
34
- rspec (3.3.0)
35
- rspec-core (~> 3.3.0)
36
- rspec-expectations (~> 3.3.0)
37
- rspec-mocks (~> 3.3.0)
38
- rspec-core (3.3.2)
39
- rspec-support (~> 3.3.0)
40
- rspec-expectations (3.3.1)
41
- diff-lcs (>= 1.2.0, < 2.0)
42
- rspec-support (~> 3.3.0)
43
- rspec-mocks (3.3.2)
44
- diff-lcs (>= 1.2.0, < 2.0)
45
- rspec-support (~> 3.3.0)
46
- rspec-support (3.3.0)
47
- sqlite3 (1.3.10)
48
- thor (0.19.1)
49
- thread_safe (0.3.5)
50
- tzinfo (1.2.2)
51
- thread_safe (~> 0.1)
52
-
53
- PLATFORMS
54
- ruby
55
-
56
- DEPENDENCIES
57
- activerecord (= 4.2.3)
58
- appraisal
59
- bundler (~> 1.10)
60
- polo!
61
- rake (~> 10.0)
62
- rspec
63
- sqlite3 (= 1.3.10)
64
-
65
- BUNDLED WITH
66
- 1.10.6