percona_migrator 0.1.0.rc.5 → 0.1.0.rc.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -1
- data/README.md +62 -26
- data/lib/active_record/connection_adapters/percona_adapter.rb +43 -98
- data/lib/percona_migrator/alter_argument.rb +11 -9
- data/lib/percona_migrator/railtie.rb +0 -12
- data/lib/percona_migrator/runner.rb +37 -3
- data/lib/percona_migrator/version.rb +1 -1
- data/percona_migrator.gemspec +2 -2
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7c92cf9bc3f2fd48fbe1277d9196037bb9d92fec
|
4
|
+
data.tar.gz: 8df8aceabfb8822fe30c3c1cae0d9055b58e2834
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a1ee2cb57ce1d7062f34d6a3c604081f2c7c7863c76e2acccf7cdadb010239e4eb94350e0c28a17eb44a90f61c7c940239682dbec5e5d2bddcd18239386b1259
|
7
|
+
data.tar.gz: e9fb460fb9eaaecee4ef5a6e5d424a23da11b9717522fd4e4914fa01d27230c5c813dac1160c460f161414077e41f64f4348a94619f0c7e43f8071abc6a57100
|
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,18 @@ Please follow the format in [Keep a Changelog](http://keepachangelog.com/)
|
|
6
6
|
|
7
7
|
## [Unreleased]
|
8
8
|
|
9
|
+
## [0.1.0.rc.6] - 2016-04-07
|
10
|
+
|
11
|
+
### Added
|
12
|
+
|
13
|
+
- Support non-ddl migrations by implementing the methods for the ActiveRecord
|
14
|
+
quering to work.
|
15
|
+
|
16
|
+
### Changed
|
17
|
+
|
18
|
+
- Refactor the PerconaAdapter to use the Runner as connection client, as all the
|
19
|
+
other adapters.
|
20
|
+
|
9
21
|
## [0.1.0.rc.5] - 2016-03-29
|
10
22
|
|
11
23
|
### Changed
|
@@ -22,7 +34,7 @@ Please follow the format in [Keep a Changelog](http://keepachangelog.com/)
|
|
22
34
|
- Support for foreing keys in db/schema.rb when using [Foreigner
|
23
35
|
gem](https://github.com/matthuhiggins/foreigner) in Rails 3 apps. This allows to
|
24
36
|
define foreign keys with #execute, but does not provide support for
|
25
|
-
|
37
|
+
add_foreign_key yet.
|
26
38
|
|
27
39
|
## [0.1.0.rc.3] - 2016-03-10
|
28
40
|
|
data/README.md
CHANGED
@@ -1,26 +1,36 @@
|
|
1
|
-
#
|
1
|
+
# Percona Migrator [![Build Status](https://travis-ci.org/redbooth/percona_migrator.svg?branch=master)](https://travis-ci.org/redbooth/percona_migrator) [![Code Climate](https://codeclimate.com/github/redbooth/percona_migrator/badges/gpa.svg)](https://codeclimate.com/github/redbooth/percona_migrator)
|
2
2
|
|
3
|
-
Percona Migrator is
|
4
|
-
DDL `ActiveRecord::
|
3
|
+
Percona Migrator is an **ActiveRecord connection adapter** that allows running
|
4
|
+
**MySQL online and non-blocking DDL** `ActiveRecord::Migration` without needing
|
5
|
+
to use a different DSL other than Rails' migrations DSL.
|
6
|
+
|
7
|
+
It uses `pt-online-schema-change` command-line tool of
|
5
8
|
[Percona
|
6
9
|
Toolkit](https://www.percona.com/doc/percona-toolkit/2.0/pt-online-schema-change.html)
|
7
|
-
which
|
8
|
-
|
9
|
-
It adds a `db:percona_migrate:up` runs your migration using the
|
10
|
-
`pt-online-schema-change` command. It will apply exactly the same changes as
|
11
|
-
if you run it with `db:migrate:up` avoiding deadlocks and without the need to
|
12
|
-
change how you write regular rails migrations.
|
13
|
-
|
14
|
-
It also disables `rake db:migrate:up` for the ddl migrations on envs with
|
15
|
-
PERCONA_TOOLKIT var set to ensure all these migrations use Percona in production.
|
10
|
+
which runs MySQL alter table statements without downtime.
|
16
11
|
|
17
12
|
## Installation
|
18
13
|
|
19
|
-
Percona Migrator relies on `pt-online-schema-change` from
|
14
|
+
Percona Migrator relies on `pt-online-schema-change` from [Percona
|
20
15
|
Toolkit](https://www.percona.com/doc/percona-toolkit/2.0/pt-online-schema-change.html)
|
21
16
|
|
22
|
-
|
23
|
-
|
17
|
+
### Mac
|
18
|
+
|
19
|
+
`brew install percona-toolkit`
|
20
|
+
|
21
|
+
### Linux
|
22
|
+
|
23
|
+
#### Ubuntu/Debian based
|
24
|
+
|
25
|
+
`apt-get install percona-toolkit`
|
26
|
+
|
27
|
+
#### Arch Linux
|
28
|
+
|
29
|
+
`pacman -S percona-toolkit perl-dbd-mysql`
|
30
|
+
|
31
|
+
#### Other distros
|
32
|
+
|
33
|
+
For other Linux distributions check out the [Percona Toolkit download
|
24
34
|
page](https://www.percona.com/downloads/percona-toolkit/) to find the package
|
25
35
|
that fits your distribution.
|
26
36
|
|
@@ -42,20 +52,46 @@ Or install it yourself as:
|
|
42
52
|
|
43
53
|
## Usage
|
44
54
|
|
45
|
-
|
46
|
-
|
47
|
-
|
55
|
+
Once you added it to your app's Gemfile, you can create and run Rails migrations
|
56
|
+
as usual.
|
57
|
+
|
58
|
+
All the `ALTER TABLE` statements will be executed with
|
59
|
+
`pt-online-schema-change`, which will provide additional output to the
|
60
|
+
migration.
|
61
|
+
|
62
|
+
### LHM support
|
63
|
+
|
64
|
+
If you moved to Soundcloud's [Lhm](https://github.com/soundcloud/lhm) already,
|
65
|
+
we got you covered. Percona Migrator overrides Lhm's DSL so that all the alter
|
66
|
+
statements also go through `pt-online-schema-change` as well.
|
67
|
+
|
68
|
+
You can keep your Lhm migrations and start using Rails migration's DSL back
|
69
|
+
again in your next migration.
|
70
|
+
|
71
|
+
## How it works
|
72
|
+
|
73
|
+
When booting your Rails app, Percona Migrator extends the
|
74
|
+
`ActiveRecord::Migration#migrate` method to reset the connection and reestablish
|
75
|
+
it using the `PerconaAdapter` instead of the one you defined in your
|
76
|
+
`config/database.yml`.
|
48
77
|
|
49
|
-
|
78
|
+
Then, when any migration DSL methods such as `add_column` or `create_table` are
|
79
|
+
executed, they all go to the
|
80
|
+
[PerconaAdapter](https://github.com/redbooth/percona_migrator/blob/master/lib/active_record/connection_adapters/percona_adapter.rb).
|
81
|
+
There, the methods that require `ALTER TABLE` SQL statements, like `add_column`,
|
82
|
+
are overriden to get executed with
|
83
|
+
[PerconaMigrator::Runner](https://github.com/redbooth/percona_migrator/blob/master/lib/percona_migrator/runner.rb),
|
84
|
+
which deals with the `pt-online-schema-change` binary. All the others, like
|
85
|
+
`create_table`, are delegated to the ActiveRecord's built in Mysql2Adapter and
|
86
|
+
so they follow the regular path.
|
50
87
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
and mark it as up. Otherwise, if the migration fails, it will still be listed as down
|
88
|
+
[PerconaMigrator::Runner](https://github.com/redbooth/percona_migrator/blob/master/lib/percona_migrator/runner.rb)
|
89
|
+
spawns a new process that runs the `pt-online-schema-change` binary present in
|
90
|
+
the system, with the apropriate arguments for the generated SQL.
|
55
91
|
|
56
|
-
|
57
|
-
|
58
|
-
|
92
|
+
When an any error occurs, an `ActiveRecord::StatementInvalid` exception is
|
93
|
+
raised and the migration is aborted, as all other ActiveRecord connection
|
94
|
+
adapters.
|
59
95
|
|
60
96
|
## Development
|
61
97
|
|
@@ -9,19 +9,19 @@ module ActiveRecord
|
|
9
9
|
# Establishes a connection to the database that's used by all Active
|
10
10
|
# Record objects.
|
11
11
|
def self.percona_connection(config)
|
12
|
-
|
13
|
-
client = connection.raw_connection
|
12
|
+
mysql2_connection = mysql2_connection(config)
|
14
13
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
cli_generator
|
14
|
+
cli_generator = PerconaMigrator::CliGenerator.new(config)
|
15
|
+
runner = PerconaMigrator::Runner.new(
|
16
|
+
logger,
|
17
|
+
cli_generator,
|
18
|
+
mysql2_connection
|
19
19
|
)
|
20
20
|
|
21
|
-
connection_options = { mysql_adapter:
|
21
|
+
connection_options = { mysql_adapter: mysql2_connection }
|
22
22
|
|
23
23
|
ConnectionAdapters::PerconaMigratorAdapter.new(
|
24
|
-
|
24
|
+
runner,
|
25
25
|
logger,
|
26
26
|
connection_options,
|
27
27
|
config
|
@@ -42,58 +42,48 @@ module ActiveRecord
|
|
42
42
|
|
43
43
|
ADAPTER_NAME = 'Percona'.freeze
|
44
44
|
|
45
|
-
def_delegators :mysql_adapter, :
|
46
|
-
:exec_insert, :exec_query, :last_inserted_id, :select, :create_table,
|
47
|
-
:drop_table
|
45
|
+
def_delegators :mysql_adapter, :last_inserted_id, :each_hash
|
48
46
|
|
49
|
-
def initialize(connection,
|
47
|
+
def initialize(connection, _logger, connection_options, _config)
|
50
48
|
super
|
49
|
+
@visitor = BindSubstitution.new(self)
|
51
50
|
@mysql_adapter = connection_options[:mysql_adapter]
|
52
|
-
@logger = logger
|
53
|
-
@runner = config[:runner]
|
54
|
-
@cli_generator = config[:cli_generator]
|
55
51
|
end
|
56
52
|
|
57
|
-
|
58
|
-
|
59
|
-
|
53
|
+
def exec_delete(sql, name, binds)
|
54
|
+
execute(to_sql(sql, binds), name)
|
55
|
+
@connection.affected_rows
|
60
56
|
end
|
57
|
+
alias :exec_update :exec_delete
|
61
58
|
|
62
|
-
|
63
|
-
|
64
|
-
# @param result [Mysql2::Result]
|
65
|
-
def each_hash(result)
|
66
|
-
if block_given?
|
67
|
-
mysql_adapter.each_hash(result, &Proc.new)
|
68
|
-
else
|
69
|
-
mysql_adapter.each_hash(result)
|
70
|
-
end
|
59
|
+
def exec_insert(sql, name, binds)
|
60
|
+
execute(to_sql(sql, binds), name)
|
71
61
|
end
|
72
62
|
|
73
|
-
def
|
74
|
-
|
63
|
+
def exec_query(sql, name = 'SQL', _binds = [])
|
64
|
+
result = execute(sql, name)
|
65
|
+
ActiveRecord::Result.new(result.fields, result.to_a)
|
75
66
|
end
|
76
67
|
|
77
|
-
#
|
78
|
-
#
|
79
|
-
|
80
|
-
|
81
|
-
# @param type [Symbol]
|
82
|
-
# @param options [Hash] optional
|
83
|
-
def add_column(table_name, column_name, type, options = {})
|
84
|
-
super
|
85
|
-
command = cli_generator.generate(table_name, @sql)
|
86
|
-
log(@sql, nil) { runner.execute(command) }
|
68
|
+
# Executes a SELECT query and returns an array of rows. Each row is an
|
69
|
+
# array of field values.
|
70
|
+
def select_rows(sql, name = nil)
|
71
|
+
execute(sql, name).to_a
|
87
72
|
end
|
88
73
|
|
89
|
-
#
|
90
|
-
#
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
74
|
+
# Executes a SELECT query and returns an array of record hashes with the
|
75
|
+
# column names as keys and column values as values.
|
76
|
+
def select(sql, name = nil, binds = [])
|
77
|
+
exec_query(sql, name, binds).to_a
|
78
|
+
end
|
79
|
+
|
80
|
+
# Returns true, as this adapter supports migrations
|
81
|
+
def supports_migrations?
|
82
|
+
true
|
83
|
+
end
|
84
|
+
|
85
|
+
def new_column(field, default, type, null, collation)
|
86
|
+
Column.new(field, default, type, null, collation)
|
97
87
|
end
|
98
88
|
|
99
89
|
# Adds a new index to the table
|
@@ -103,10 +93,7 @@ module ActiveRecord
|
|
103
93
|
# @param options [Hash] optional
|
104
94
|
def add_index(table_name, column_name, options = {})
|
105
95
|
index_name, index_type, index_columns, index_options = add_index_options(table_name, column_name, options)
|
106
|
-
execute "ADD #{index_type} INDEX #{quote_column_name(index_name)} (#{index_columns})#{index_options}"
|
107
|
-
|
108
|
-
command = cli_generator.generate(table_name, @sql)
|
109
|
-
log(@sql, nil) { runner.execute(command) }
|
96
|
+
execute "ALTER TABLE #{quote_table_name(table_name)} ADD #{index_type} INDEX #{quote_column_name(index_name)} (#{index_columns})#{index_options}"
|
110
97
|
end
|
111
98
|
|
112
99
|
# Remove the given index from the table.
|
@@ -115,59 +102,17 @@ module ActiveRecord
|
|
115
102
|
# @param options [Hash] optional
|
116
103
|
def remove_index(table_name, options = {})
|
117
104
|
index_name = index_name_for_remove(table_name, options)
|
118
|
-
execute "DROP INDEX #{quote_column_name(index_name)}"
|
119
|
-
|
120
|
-
command = cli_generator.generate(table_name, @sql)
|
121
|
-
log(@sql, nil) { runner.execute(command) }
|
122
|
-
end
|
123
|
-
|
124
|
-
# Records the SQL statement to be executed. This is used to then delegate
|
125
|
-
# the execution to Percona's pt-online-schema-change.
|
126
|
-
#
|
127
|
-
# @param sql [String]
|
128
|
-
# @param _name [String] optional
|
129
|
-
def execute(sql, _name = nil)
|
130
|
-
@sql = sql
|
131
|
-
true
|
105
|
+
execute "ALTER TABLE #{quote_table_name(table_name)} DROP INDEX #{quote_column_name(index_name)}"
|
132
106
|
end
|
133
107
|
|
134
|
-
#
|
135
|
-
#
|
136
|
-
|
137
|
-
# @param sql [String]
|
138
|
-
# @param name [String]
|
139
|
-
def percona_execute(sql, name)
|
140
|
-
if alter_statement?(sql)
|
141
|
-
command = cli_generator.parse_statement(sql)
|
142
|
-
log(sql, nil) { runner.execute(command) }
|
143
|
-
else
|
144
|
-
mysql_adapter.execute(sql, name)
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
# This abstract method leaves up to the connection adapter freeing the
|
149
|
-
# result, if it needs to. Check out: https://github.com/rails/rails/blob/330c6af05c8b188eb072afa56c07d5fe15767c3c/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb#L247
|
150
|
-
#
|
151
|
-
# @param sql [String]
|
152
|
-
# @param name [String] optional
|
153
|
-
def execute_and_free(sql, name = nil)
|
154
|
-
yield mysql_adapter.execute(sql, name)
|
155
|
-
end
|
156
|
-
|
157
|
-
def error_number(exception)
|
108
|
+
# Returns the MySQL error number from the exception. The
|
109
|
+
# AbstractMysqlAdapter requires it to be implemented
|
110
|
+
def error_number(_exception)
|
158
111
|
end
|
159
112
|
|
160
113
|
private
|
161
114
|
|
162
|
-
attr_reader :mysql_adapter
|
163
|
-
|
164
|
-
# Checks whether the sql statement is an ALTER TABLE
|
165
|
-
#
|
166
|
-
# @param sql [String]
|
167
|
-
# @return [Boolean]
|
168
|
-
def alter_statement?(sql)
|
169
|
-
sql =~ /alter table/i
|
170
|
-
end
|
115
|
+
attr_reader :mysql_adapter
|
171
116
|
end
|
172
117
|
end
|
173
118
|
end
|
@@ -1,30 +1,32 @@
|
|
1
1
|
module PerconaMigrator
|
2
|
+
class InvalidAlterStatement < StandardError; end
|
2
3
|
|
3
4
|
# Represents the '--alter' argument of Percona's pt-online-schema-change
|
4
5
|
# See https://www.percona.com/doc/percona-toolkit/2.0/pt-online-schema-change.html
|
5
6
|
class AlterArgument
|
6
|
-
ALTER_TABLE_REGEX =
|
7
|
+
ALTER_TABLE_REGEX = /\AALTER TABLE `(\w+)` /
|
8
|
+
|
9
|
+
attr_reader :table_name
|
7
10
|
|
8
11
|
# Constructor
|
9
12
|
#
|
10
13
|
# @param statement [String]
|
14
|
+
# @raise [InvalidAlterStatement] if the statement is not an ALTER TABLE
|
11
15
|
def initialize(statement)
|
12
16
|
@statement = statement
|
17
|
+
|
18
|
+
match = statement.match(ALTER_TABLE_REGEX)
|
19
|
+
raise InvalidAlterStatement unless match
|
20
|
+
|
21
|
+
@table_name = match.captures[0]
|
13
22
|
end
|
14
23
|
|
15
|
-
# Returns the '--alter' pt-online-schema-change
|
24
|
+
# Returns the '--alter' pt-online-schema-change argument as a string. See
|
16
25
|
# https://www.percona.com/doc/percona-toolkit/2.0/pt-online-schema-change.html
|
17
26
|
def to_s
|
18
27
|
"--alter \"#{parsed_statement}\""
|
19
28
|
end
|
20
29
|
|
21
|
-
# Returns the name of the table the alter statement refers to
|
22
|
-
#
|
23
|
-
# @return [String]
|
24
|
-
def table_name
|
25
|
-
statement.match(ALTER_TABLE_REGEX).captures[0]
|
26
|
-
end
|
27
|
-
|
28
30
|
private
|
29
31
|
|
30
32
|
attr_reader :statement
|
@@ -48,18 +48,6 @@ module PerconaMigrator
|
|
48
48
|
connection_config.merge(adapter: 'percona')
|
49
49
|
)
|
50
50
|
end
|
51
|
-
|
52
|
-
# It executes the passed statement through the PerconaMigratorAdapter
|
53
|
-
# if it's an alter statement. It uses the mysql adapter otherwise.
|
54
|
-
#
|
55
|
-
# This is because +pt-online-schema-change+ is intended for alter
|
56
|
-
# statements only.
|
57
|
-
#
|
58
|
-
# @param sql [String]
|
59
|
-
# @param name [String] optional
|
60
|
-
def execute(sql, name = nil)
|
61
|
-
percona_execute(sql, name)
|
62
|
-
end
|
63
51
|
end
|
64
52
|
end
|
65
53
|
end
|
@@ -47,11 +47,35 @@ module PerconaMigrator
|
|
47
47
|
# Constructor
|
48
48
|
#
|
49
49
|
# @param logger [IO]
|
50
|
-
def initialize(logger)
|
50
|
+
def initialize(logger, cli_generator, mysql_adapter)
|
51
51
|
@logger = logger
|
52
|
+
@cli_generator = cli_generator
|
53
|
+
@mysql_adapter = mysql_adapter
|
52
54
|
@status = nil
|
53
55
|
end
|
54
56
|
|
57
|
+
# Executes the passed sql statement using pt-online-schema-change for ALTER
|
58
|
+
# TABLE statements, or the specified mysql adapter otherwise.
|
59
|
+
#
|
60
|
+
# @param sql [String]
|
61
|
+
def query(sql)
|
62
|
+
if alter_statement?(sql)
|
63
|
+
command = cli_generator.parse_statement(sql)
|
64
|
+
execute(command)
|
65
|
+
else
|
66
|
+
mysql_adapter.execute(sql)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# Returns the number of rows affected by the last UPDATE, DELETE or INSERT
|
71
|
+
# statements
|
72
|
+
#
|
73
|
+
# @return [Integer]
|
74
|
+
def affected_rows
|
75
|
+
mysql_adapter.raw_connection.affected_rows
|
76
|
+
end
|
77
|
+
|
78
|
+
# TODO: rename it so we don't confuse it with AR's #execute
|
55
79
|
# Runs and logs the given command
|
56
80
|
#
|
57
81
|
# @param command [String]
|
@@ -64,7 +88,15 @@ module PerconaMigrator
|
|
64
88
|
|
65
89
|
private
|
66
90
|
|
67
|
-
attr_reader :command, :logger, :status
|
91
|
+
attr_reader :command, :logger, :status, :cli_generator, :mysql_adapter
|
92
|
+
|
93
|
+
# Checks whether the sql statement is an ALTER TABLE
|
94
|
+
#
|
95
|
+
# @param sql [String]
|
96
|
+
# @return [Boolean]
|
97
|
+
def alter_statement?(sql)
|
98
|
+
sql =~ /\Aalter table/i
|
99
|
+
end
|
68
100
|
|
69
101
|
# Logs the start and end of the execution
|
70
102
|
#
|
@@ -84,7 +116,9 @@ module PerconaMigrator
|
|
84
116
|
|
85
117
|
# Executes the command outputing any errors
|
86
118
|
#
|
87
|
-
# @raise [
|
119
|
+
# @raise [NoStatusError] if the spawned process' status can't be retrieved
|
120
|
+
# @raise [SignalError] if the spawned process receives a signal
|
121
|
+
# @raise [CommandNotFoundError] if pt-online-schema-change can't be found
|
88
122
|
def run_command
|
89
123
|
message = nil
|
90
124
|
Open3.popen3(command) do |_stdin, stdout, stderr, waith_thr|
|
data/percona_migrator.gemspec
CHANGED
@@ -7,8 +7,8 @@ require 'percona_migrator/version'
|
|
7
7
|
Gem::Specification.new do |spec|
|
8
8
|
spec.name = 'percona_migrator'
|
9
9
|
spec.version = PerconaMigrator::VERSION
|
10
|
-
spec.authors = ['Ilya Zayats', 'Pau Pérez', 'Fran Casas']
|
11
|
-
spec.email = ['ilya.zayats@redbooth.com', 'pau.perez@redbooth.com', 'fran.casas@redbooth.com']
|
10
|
+
spec.authors = ['Ilya Zayats', 'Pau Pérez', 'Fran Casas', 'Jorge Morante']
|
11
|
+
spec.email = ['ilya.zayats@redbooth.com', 'pau.perez@redbooth.com', 'fran.casas@redbooth.com', 'jorge.morante@redbooth.com']
|
12
12
|
|
13
13
|
spec.summary = %q{pt-online-schema-change runner for ActiveRecord migrations}
|
14
14
|
spec.description = %q{Execute your ActiveRecord migrations with Percona's pt-online-schema-change}
|
metadata
CHANGED
@@ -1,16 +1,17 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: percona_migrator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.0.rc.
|
4
|
+
version: 0.1.0.rc.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ilya Zayats
|
8
8
|
- Pau Pérez
|
9
9
|
- Fran Casas
|
10
|
+
- Jorge Morante
|
10
11
|
autorequire:
|
11
12
|
bindir: bin
|
12
13
|
cert_chain: []
|
13
|
-
date: 2016-
|
14
|
+
date: 2016-04-07 00:00:00.000000000 Z
|
14
15
|
dependencies:
|
15
16
|
- !ruby/object:Gem::Dependency
|
16
17
|
name: rails
|
@@ -127,6 +128,7 @@ email:
|
|
127
128
|
- ilya.zayats@redbooth.com
|
128
129
|
- pau.perez@redbooth.com
|
129
130
|
- fran.casas@redbooth.com
|
131
|
+
- jorge.morante@redbooth.com
|
130
132
|
executables: []
|
131
133
|
extensions: []
|
132
134
|
extra_rdoc_files: []
|