cassandro 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,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: