cassandro 0.2.0 → 0.3.0

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
- ZjdiYjhlYzUyNGRhZjJhNzQ5Y2I5NWQ5Nzk0OTkzMTVjYzEzZDBiOA==
4
+ NzRiYWJkNjAzZjJhODZjZDIzMGQzY2Q4MjlmM2QxOGUwMmM4ZjQxMQ==
5
5
  data.tar.gz: !binary |-
6
- M2RjMGIxMWRiYzYxMDIxMTgxYjA5ODY5YmM0ZjQ5YzU2NGY5Y2JiNA==
6
+ NDM2NzY2N2FiN2RmYzQ1NzE2N2JjZDIxOGFlNDAyMDg2YTQwZjQzYQ==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- MjZmMGE4NzA3ZDdlNDViYzI2M2IyM2I3NWYzY2Q3ZThjYzBjODk1Yzg1NThk
10
- NTBjMjcyMDE4MTc2ZDhlZWU4YzNjMjhmM2VkOWMzMzY0MWRkNTEyOWY2YTFh
11
- MDE1OTA3NzJkOGFjZGRkNGI3N2VkMDk4Mjk1MjUxZWFiZmQzNjY=
9
+ Y2I4YjVkMTFkZjM5MmFiZDlmNGU2MDJjNzAzMjAxYWIzYzc0NmQ0MWI0NDBj
10
+ NjBiYzVmNTAzMjk0ZmI1MzUwM2E4ZTUyNTgyMjliODQ3NGQyZDE2NTlkOWQ1
11
+ M2QyYWUzNDQxNWE4NjM3ZjUyYTk4OWI4NjlhNDRmOTZmNzNmMTg=
12
12
  data.tar.gz: !binary |-
13
- ODE4YzQzY2IzMDI0NGM3MThhOTVkMzgxZmE4ODA5NDNiOGM2MmU3ZGU2Y2Y2
14
- ZDA1NGUyMmRlYmI2MDQxNWJjMTYzYzY5MDY1OWQ3ZTVkZTlkZTY4ZGNlYTZl
15
- MzVmNzYzMWEwZWY0YzU1MjdkNGY5ZWQyNTQ4NDkzY2EyMzI3ZTE=
13
+ YWQ1ZTE2ZTk0NmI2YWNmMTczMWNlZTI3ZjdmMTllYjY4N2JlMDNmMDRmNGFk
14
+ MTYzODhjOGM2MTExNzE3ZmExZTVkMzM4NDlkYzNkNzBhNjM0OGExNTJkZmQ0
15
+ NzNmNzU5NjRlYjg0ZTBlZDYzNTVkYjg5NzU4M2ZlM2QxOTI4MWQ=
data/README.md CHANGED
@@ -223,9 +223,67 @@ user.errors
223
223
 
224
224
  ```
225
225
 
226
+ ## Migrations
227
+
228
+ Define your migrations by extending from `Cassandro::Migration`
229
+
230
+ ```ruby
231
+ class UserMigration < Cassandro::Migration
232
+ version 1
233
+
234
+ def up
235
+ execute <<-TABLEDEF
236
+ CREATE TABLE users (
237
+ id UUID,
238
+ first_name VARCHAR,
239
+ last_name VARCHAR,
240
+ email VARCHAR,
241
+ PRIMARY KEY(id, email)
242
+ )
243
+ TABLEDEF
244
+ end
245
+
246
+ def down
247
+ execute <<-QUERY
248
+ DROP TABLE users;
249
+ QUERY
250
+ end
251
+ end
252
+
253
+ class UserGenderMigration < Cassandro::Migration
254
+
255
+ version 2
256
+
257
+ def up
258
+ execute <<-TABLEUPDATE
259
+ ALTER TABLE users ADD gender VARCHAR
260
+ TABLEUPDATE
261
+ end
262
+
263
+ def down
264
+ execute <<-QUERY
265
+ ALTER TABLE users DROP gender
266
+ QUERY
267
+ end
268
+ end
269
+ ```
270
+
271
+ Then use `Cassandro::Migrator` to run your migrations
272
+
273
+ ```ruby
274
+ Cassandro.connect(hosts: ['127.0.0.1'], keyspace: 'some_keyspace')
275
+
276
+ migrator = Cassandro::Migrator.new('./path/to/migrations', Logger.new(STDOUT))
277
+
278
+ migrator.migrate!(:up) #migrates to last version
279
+ migrator.migrate!(:down) #apply all downgrades
280
+
281
+ migrator.migrate!(:up, 2) #migrates up to version 2
282
+ migrator.migrate!(:down, 1) #migrates down to version 1
283
+ ```
284
+
226
285
  ## TODO
227
286
 
228
- * Migrations
229
287
  * Support Index
230
288
  * Better queries
231
289
  * Better documentation
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = "cassandro"
5
- s.version = "0.2.0"
5
+ s.version = "0.3.0"
6
6
  s.summary = "Ruby ORM for Apache Cassandra"
7
7
  s.license = "MIT"
8
8
  s.description = "Lightweight Apache Cassandra ORM for Ruby"
@@ -2,3 +2,4 @@ require_relative './cassandro/core'
2
2
  require_relative './cassandro/support/hash'
3
3
  require_relative './cassandro/ext/soft_delete'
4
4
  require_relative './cassandro/model'
5
+ require_relative './cassandro/migrations'
@@ -0,0 +1,29 @@
1
+ module Cassandro
2
+ class Migration
3
+ @@migrations = []
4
+
5
+ def up; end
6
+
7
+ def down; end
8
+
9
+ def execute(query)
10
+ Cassandro.client.execute(query)
11
+ end
12
+
13
+ def self.version(version_number)
14
+ @@migrations[version_number.to_i] = self.name
15
+ end
16
+
17
+ def self.migrations
18
+ @@migrations
19
+ end
20
+
21
+ def self.apply(direction = :up)
22
+ new.send(direction)
23
+ end
24
+
25
+ def self.clean
26
+ @@migrations = []
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,74 @@
1
+ require 'logger'
2
+
3
+ module Cassandro
4
+ class Migrator
5
+
6
+ def initialize(path, logger = ::Logger.new(STDOUT))
7
+ Dir["#{path}/**/*.rb"].each { |file| require file }
8
+ @migrations = Cassandro::Migration.migrations
9
+ @logger = logger
10
+
11
+ Cassandro.client.execute CassandroMigration.schema
12
+
13
+ version = CassandroMigration[name: 'version'] || CassandroMigration.create(name: 'version', value: "0")
14
+
15
+ @current_version = version
16
+ end
17
+
18
+ def migrate!(direction, to = '.')
19
+ from = @current_version.value.to_i
20
+
21
+ case direction
22
+ when :up
23
+ to = (to == '.' ? @migrations.size - 1 : to).to_i
24
+ return @logger.error "Can't migrate up to a prev version (#{from} to #{to})" if to < from
25
+ return @logger.info "Database is up to date" if to == from
26
+
27
+ @logger.info "Upgrading database from version #{from} to #{to}"
28
+ begin
29
+ @migrations[from+1..to].each do |migration|
30
+ Object.const_get(migration).apply(:up)
31
+ end
32
+ @current_version.update_attributes(value: to.to_s)
33
+ @logger.info "OK"
34
+ rescue => e
35
+ @logger.error e.message
36
+ end
37
+ when :down
38
+ to = (to == '.' ? 0 : to).to_i
39
+ return @logger.error "Can't migrate down to a higher version (#{from} to #{to})" if to > from
40
+ return @logger.info "Database is up to date" if to == from
41
+
42
+ @logger.info "Drowngrading database from version #{from} to #{to}"
43
+ begin
44
+ @migrations[to+1..from].reverse_each do |migration|
45
+ Object.const_get(migration).apply(:down)
46
+ end
47
+ @current_version.update_attributes(value: to.to_s)
48
+ @logger.info "OK"
49
+ rescue => e
50
+ @logger.error e.message
51
+ end
52
+ end
53
+ end
54
+
55
+ class CassandroMigration < Cassandro::Model
56
+ table :cassandro_migrations
57
+
58
+ attribute :name, :text
59
+ attribute :value, :text
60
+
61
+ primary_key [:name]
62
+
63
+ def self.schema
64
+ <<-TABLEDEF
65
+ CREATE TABLE IF NOT EXISTS cassandro_migrations (
66
+ name VARCHAR,
67
+ value VARCHAR,
68
+ PRIMARY KEY (name)
69
+ )
70
+ TABLEDEF
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,2 @@
1
+ require_relative 'ext/migration'
2
+ require_relative 'ext/migrator'
@@ -0,0 +1,21 @@
1
+ require_relative 'helper'
2
+
3
+ Protest.describe "Cassandro Migration" do
4
+ setup do
5
+ Cassandro.connect(hosts: ['127.0.0.1'], keyspace: 'cassandro_test')
6
+ end
7
+
8
+ test "enqueue migrations" do
9
+ class FirstMigration < Cassandro::Migration
10
+ version 1
11
+ end
12
+
13
+ class SecondMigration < Cassandro::Migration
14
+ version 2
15
+ end
16
+
17
+ assert_equal 2, Cassandro::Migration.migrations.compact.size
18
+ assert_equal "FirstMigration", Cassandro::Migration.migrations[1]
19
+ assert_equal "SecondMigration", Cassandro::Migration.migrations[2]
20
+ end
21
+ end
@@ -0,0 +1,66 @@
1
+ require_relative 'helper'
2
+
3
+ Protest.describe "Cassandro Migrator" do
4
+ setup do
5
+ #Cassandro::Migration.cleaassandra::Errors::InvalidError
6
+ Cassandro.client.execute("DROP TABLE IF EXISTS users")
7
+ Cassandro.client.execute("DROP TABLE IF EXISTS animals")
8
+ Cassandro.client.execute("DROP TABLE IF EXISTS cassandro_migrations")
9
+ @migrator = Cassandro::Migrator.new("./test/support/migrations", Logger.new('/dev/null'))
10
+ end
11
+
12
+ context "Migrating up" do
13
+
14
+ test "to last version" do
15
+ @migrator.migrate!(:up)
16
+ version = Cassandro::Migrator::CassandroMigration[name: 'version']
17
+
18
+ assert_equal 3, version.value.to_i
19
+ assert_equal Cassandra::Results::Paged, Cassandro.client.execute("SELECT * FROM users").class
20
+ assert_equal Cassandra::Results::Paged, Cassandro.client.execute("SELECT * FROM animals").class
21
+ end
22
+
23
+ test "to specific version" do
24
+ @migrator.migrate!(:up, 1)
25
+ version = Cassandro::Migrator::CassandroMigration[name: 'version']
26
+
27
+ assert_equal 1, version.value.to_i
28
+ assert_equal Cassandra::Results::Paged, Cassandro.client.execute("SELECT * FROM users").class
29
+ assert_raise Cassandra::Errors::InvalidError, "unconfigured columnfamily animals" do
30
+ Cassandro.client.execute("SELECT * FROM animals")
31
+ end
32
+ end
33
+ end
34
+
35
+ context 'Migrating down' do
36
+ setup do
37
+ @migrator.migrate!(:up)
38
+ end
39
+
40
+ test "to version 0" do
41
+ @migrator.migrate!(:down)
42
+
43
+ version = Cassandro::Migrator::CassandroMigration[name: 'version']
44
+
45
+ assert_equal 0, version.value.to_i
46
+ assert_raise Cassandra::Errors::InvalidError, "unconfigured columnfamily users" do
47
+ Cassandro.client.execute("SELECT * FROM users")
48
+ end
49
+ assert_raise Cassandra::Errors::InvalidError, "unconfigured columnfamily animals" do
50
+ Cassandro.client.execute("SELECT * FROM animals")
51
+ end
52
+ end
53
+
54
+ test "to specific version" do
55
+ @migrator.migrate!(:down, 1)
56
+
57
+ version = Cassandro::Migrator::CassandroMigration[name: 'version']
58
+
59
+ assert_equal 1, version.value.to_i
60
+ assert_equal Cassandra::Results::Paged, Cassandro.client.execute("SELECT * FROM users").class
61
+ assert_raise Cassandra::Errors::InvalidError, "unconfigured columnfamily animals" do
62
+ Cassandro.client.execute("SELECT * FROM animals")
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,20 @@
1
+ class AnimalMigration < Cassandro::Migration
2
+ version 3
3
+
4
+ def up
5
+ execute <<-TABLEDEF
6
+ CREATE TABLE animals (
7
+ family VARCHAR,
8
+ genus VARCHAR,
9
+ name VARCHAR,
10
+ PRIMARY KEY(family, genus)
11
+ )
12
+ TABLEDEF
13
+ end
14
+
15
+ def down
16
+ execute <<-QUERY
17
+ DROP TABLE animals;
18
+ QUERY
19
+ end
20
+ end
@@ -0,0 +1,16 @@
1
+ class UserGenderMigration < Cassandro::Migration
2
+
3
+ version 2
4
+
5
+ def up
6
+ execute <<-TABLEUPDATE
7
+ ALTER TABLE users ADD gender VARCHAR
8
+ TABLEUPDATE
9
+ end
10
+
11
+ def down
12
+ execute <<-QUERY
13
+ ALTER TABLE users DROP gender
14
+ QUERY
15
+ end
16
+ end
@@ -0,0 +1,23 @@
1
+ class UserMigration < Cassandro::Migration
2
+
3
+ version 1
4
+
5
+ def up
6
+ execute <<-TABLEDEF
7
+ CREATE TABLE users (
8
+ id UUID,
9
+ first_name VARCHAR,
10
+ last_name VARCHAR,
11
+ email VARCHAR,
12
+ PRIMARY KEY(id, email)
13
+ )
14
+ TABLEDEF
15
+ end
16
+
17
+ def down
18
+ execute <<-QUERY
19
+ DROP TABLE users;
20
+ QUERY
21
+ end
22
+ end
23
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cassandro
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
  - Lautaro Orazi
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-11-03 00:00:00.000000000 Z
12
+ date: 2014-12-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: cassandra-driver
@@ -55,13 +55,21 @@ files:
55
55
  - cassandro.gemspec
56
56
  - lib/cassandro.rb
57
57
  - lib/cassandro/core.rb
58
+ - lib/cassandro/ext/migration.rb
59
+ - lib/cassandro/ext/migrator.rb
58
60
  - lib/cassandro/ext/soft_delete.rb
61
+ - lib/cassandro/migrations.rb
59
62
  - lib/cassandro/model.rb
60
63
  - lib/cassandro/support/hash.rb
61
64
  - rakefile
65
+ - test/cassandro_migration_test.rb
66
+ - test/cassandro_migrator_test.rb
62
67
  - test/cassandro_model_test.rb
63
68
  - test/cassandro_test.rb
64
69
  - test/helper.rb
70
+ - test/support/migrations/animals_table.rb
71
+ - test/support/migrations/update_user_table.rb
72
+ - test/support/migrations/user_table.rb
65
73
  - test/support/tables.rb
66
74
  homepage: https://github.com/tarolandia/cassandro
67
75
  licenses: