cassanity 0.4.0 → 0.5.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.
Files changed (73) hide show
  1. data/.gitignore +2 -1
  2. data/.travis.yml +1 -0
  3. data/Gemfile +3 -0
  4. data/Guardfile +0 -2
  5. data/README.md +11 -0
  6. data/doc/Instrumentation.md +40 -0
  7. data/doc/Migrations.md +132 -0
  8. data/examples/keyspaces.rb +11 -7
  9. data/lib/cassanity/argument_generators/column_family_delete.rb +1 -1
  10. data/lib/cassanity/argument_generators/columns.rb +33 -0
  11. data/lib/cassanity/argument_generators/where_clause.rb +1 -1
  12. data/lib/cassanity/client.rb +3 -1
  13. data/lib/cassanity/column.rb +48 -0
  14. data/lib/cassanity/column_family.rb +21 -2
  15. data/lib/cassanity/connection.rb +4 -8
  16. data/lib/cassanity/error.rb +18 -11
  17. data/lib/cassanity/executors/cassandra_cql.rb +79 -50
  18. data/lib/cassanity/instrumentation/log_subscriber.rb +4 -5
  19. data/lib/cassanity/instrumentation/metriks.rb +6 -0
  20. data/lib/cassanity/instrumentation/metriks_subscriber.rb +16 -0
  21. data/lib/cassanity/instrumentation/statsd.rb +6 -0
  22. data/lib/cassanity/instrumentation/statsd_subscriber.rb +22 -0
  23. data/lib/cassanity/instrumentation/subscriber.rb +58 -0
  24. data/lib/cassanity/instrumenters/memory.rb +0 -1
  25. data/lib/cassanity/keyspace.rb +10 -8
  26. data/lib/cassanity/migration.rb +125 -0
  27. data/lib/cassanity/migration_proxy.rb +76 -0
  28. data/lib/cassanity/migrator.rb +154 -0
  29. data/lib/cassanity/result_transformers/column_families.rb +20 -0
  30. data/lib/cassanity/result_transformers/columns.rb +21 -0
  31. data/lib/cassanity/result_transformers/keyspaces.rb +21 -0
  32. data/lib/cassanity/result_transformers/mirror.rb +1 -1
  33. data/lib/cassanity/result_transformers/result_to_array.rb +1 -1
  34. data/lib/cassanity/retry_strategies/exponential_backoff.rb +43 -0
  35. data/lib/cassanity/retry_strategies/retry_n_times.rb +29 -0
  36. data/lib/cassanity/retry_strategies/retry_strategy.rb +35 -0
  37. data/lib/cassanity/version.rb +1 -1
  38. data/spec/helper.rb +8 -0
  39. data/spec/integration/cassanity/column_family_spec.rb +36 -25
  40. data/spec/integration/cassanity/connection_spec.rb +11 -11
  41. data/spec/integration/cassanity/fixtures/migrations/20130224135000_create_users.rb +17 -0
  42. data/spec/integration/cassanity/fixtures/migrations/20130225135002_create_apps.rb +15 -0
  43. data/spec/integration/cassanity/fixtures/migrations/20130226135004_add_username_to_users.rb +9 -0
  44. data/spec/integration/cassanity/instrumentation/log_subscriber_spec.rb +71 -0
  45. data/spec/integration/cassanity/instrumentation/metriks_subscriber_spec.rb +48 -0
  46. data/spec/integration/cassanity/instrumentation/statsd_subscriber_spec.rb +58 -0
  47. data/spec/integration/cassanity/keyspace_spec.rb +21 -21
  48. data/spec/integration/cassanity/migration_spec.rb +157 -0
  49. data/spec/integration/cassanity/migrator_spec.rb +212 -0
  50. data/spec/support/cassanity_helpers.rb +21 -17
  51. data/spec/support/fake_udp_socket.rb +27 -0
  52. data/spec/unit/cassanity/argument_generators/batch_spec.rb +5 -5
  53. data/spec/unit/cassanity/argument_generators/column_family_delete_spec.rb +20 -6
  54. data/spec/unit/cassanity/argument_generators/column_family_update_spec.rb +6 -6
  55. data/spec/unit/cassanity/argument_generators/columns_spec.rb +45 -0
  56. data/spec/unit/cassanity/argument_generators/keyspace_create_spec.rb +1 -1
  57. data/spec/unit/cassanity/argument_generators/keyspace_drop_spec.rb +1 -1
  58. data/spec/unit/cassanity/argument_generators/keyspace_use_spec.rb +1 -1
  59. data/spec/unit/cassanity/argument_generators/where_clause_spec.rb +2 -2
  60. data/spec/unit/cassanity/client_spec.rb +10 -3
  61. data/spec/unit/cassanity/column_family_spec.rb +20 -3
  62. data/spec/unit/cassanity/column_spec.rb +76 -0
  63. data/spec/unit/cassanity/connection_spec.rb +1 -1
  64. data/spec/unit/cassanity/error_spec.rb +7 -2
  65. data/spec/unit/cassanity/executors/cassandra_cql_spec.rb +76 -23
  66. data/spec/unit/cassanity/keyspace_spec.rb +38 -13
  67. data/spec/unit/cassanity/migration_proxy_spec.rb +81 -0
  68. data/spec/unit/cassanity/migration_spec.rb +12 -0
  69. data/spec/unit/cassanity/migrator_spec.rb +20 -0
  70. data/spec/unit/cassanity/retry_strategies/exponential_backoff_spec.rb +37 -0
  71. data/spec/unit/cassanity/retry_strategies/retry_n_times_spec.rb +47 -0
  72. data/spec/unit/cassanity/retry_strategies/retry_strategy_spec.rb +27 -0
  73. metadata +56 -4
@@ -1,35 +1,39 @@
1
1
  module CassanityHelpers
2
- def client_keyspace?(client, name)
3
- client.keyspaces.map(&:name).include?(name.to_s)
2
+ def driver_keyspace?(driver, name)
3
+ driver.keyspaces.map(&:name).include?(name.to_s)
4
4
  end
5
5
 
6
- def client_create_keyspace(client, name)
7
- unless client_keyspace?(client, name)
8
- client.execute("CREATE KEYSPACE #{name} WITH strategy_class = 'SimpleStrategy' AND strategy_options:replication_factor = 1")
6
+ def driver_create_keyspace(driver, name)
7
+ unless driver_keyspace?(driver, name)
8
+ driver.execute("CREATE KEYSPACE #{name} WITH strategy_class = 'SimpleStrategy' AND strategy_options:replication_factor = 1")
9
9
  end
10
- client.execute("USE #{name}")
10
+ driver.execute("USE #{name}")
11
11
  end
12
12
 
13
- def client_drop_keyspace(client, name)
14
- if client_keyspace?(client, name)
15
- client.execute("DROP KEYSPACE #{name}")
13
+ def driver_drop_keyspace(driver, name)
14
+ if driver_keyspace?(driver, name)
15
+ driver.execute("DROP KEYSPACE #{name}")
16
16
  end
17
17
  end
18
18
 
19
- def client_column_family?(client, name)
20
- client.schema.column_family_names.include?(name.to_s)
19
+ def driver_column_family?(driver, name)
20
+ driver.schema.column_family_names.include?(name.to_s)
21
21
  end
22
22
 
23
- def client_create_column_family(client, name, columns = nil)
23
+ def driver_create_column_family(driver, name, columns = nil)
24
24
  columns ||= "id text PRIMARY KEY, name text"
25
- unless client_column_family?(client, name)
26
- client.execute("CREATE COLUMNFAMILY #{name} (#{columns})")
25
+ unless driver_column_family?(driver, name)
26
+ driver.execute("CREATE COLUMNFAMILY #{name} (#{columns})")
27
27
  end
28
28
  end
29
29
 
30
- def client_drop_column_family(client, name)
31
- if client_column_family?(client, name)
32
- client.execute("DROP COLUMNFAMILY #{name}")
30
+ def driver_drop_column_family(driver, name)
31
+ if driver_column_family?(driver, name)
32
+ driver.execute("DROP COLUMNFAMILY #{name}")
33
33
  end
34
34
  end
35
+
36
+ def cassandra_error(err)
37
+ CassandraCQL::Error::InvalidRequestException.new(err)
38
+ end
35
39
  end
@@ -0,0 +1,27 @@
1
+ class FakeUDPSocket
2
+ attr_reader :buffer
3
+
4
+ def initialize
5
+ @buffer = []
6
+ end
7
+
8
+ def send(message, *rest)
9
+ @buffer.push [message]
10
+ end
11
+
12
+ def recv
13
+ @buffer.shift
14
+ end
15
+
16
+ def clear
17
+ @buffer = []
18
+ end
19
+
20
+ def to_s
21
+ inspect
22
+ end
23
+
24
+ def inspect
25
+ "<FakeUDPSocket: #{@buffer.inspect}>"
26
+ end
27
+ end
@@ -4,7 +4,7 @@ require 'cassanity/argument_generators/batch'
4
4
  describe Cassanity::ArgumentGenerators::Batch do
5
5
  describe "#call" do
6
6
  it "returns array of arguments" do
7
- cql = "BEGIN BATCH INSERT INTO users (id) VALUES (?) UPDATE users SET name = ? WHERE id = ? DELETE FROM users WHERE id = ? APPLY BATCH"
7
+ cql = "BEGIN BATCH INSERT INTO users (id) VALUES (?) UPDATE users SET name = ? WHERE \"id\" = ? DELETE FROM users WHERE \"id\" = ? APPLY BATCH"
8
8
  subject.call({
9
9
  modifications: [
10
10
  [:insert, column_family_name: :users, data: {id: '1'}],
@@ -16,7 +16,7 @@ describe Cassanity::ArgumentGenerators::Batch do
16
16
 
17
17
  context "with :column_family_name" do
18
18
  it "merges column_family_name with each set of modifications" do
19
- cql = "BEGIN BATCH INSERT INTO users (id) VALUES (?) UPDATE users SET name = ? WHERE id = ? APPLY BATCH"
19
+ cql = "BEGIN BATCH INSERT INTO users (id) VALUES (?) UPDATE users SET name = ? WHERE \"id\" = ? APPLY BATCH"
20
20
  subject.call({
21
21
  column_family_name: :users,
22
22
  modifications: [
@@ -27,7 +27,7 @@ describe Cassanity::ArgumentGenerators::Batch do
27
27
  end
28
28
 
29
29
  it "does not override command argument name" do
30
- cql = "BEGIN BATCH INSERT INTO users (id) VALUES (?) UPDATE other_column_family SET name = ? WHERE id = ? APPLY BATCH"
30
+ cql = "BEGIN BATCH INSERT INTO users (id) VALUES (?) UPDATE other_column_family SET name = ? WHERE \"id\" = ? APPLY BATCH"
31
31
  subject.call({
32
32
  column_family_name: :users,
33
33
  modifications: [
@@ -40,7 +40,7 @@ describe Cassanity::ArgumentGenerators::Batch do
40
40
 
41
41
  context "with :keyspace_name" do
42
42
  it "merges column_family_name with each set of modifications" do
43
- cql = "BEGIN BATCH INSERT INTO analytics.users (id) VALUES (?) UPDATE analytics.users SET name = ? WHERE id = ? APPLY BATCH"
43
+ cql = "BEGIN BATCH INSERT INTO analytics.users (id) VALUES (?) UPDATE analytics.users SET name = ? WHERE \"id\" = ? APPLY BATCH"
44
44
  subject.call({
45
45
  keyspace_name: :analytics,
46
46
  modifications: [
@@ -51,7 +51,7 @@ describe Cassanity::ArgumentGenerators::Batch do
51
51
  end
52
52
 
53
53
  it "does not override command argument keyspace_name" do
54
- cql = "BEGIN BATCH INSERT INTO other_keyspace_name.users (id) VALUES (?) UPDATE analytics.users SET name = ? WHERE id = ? APPLY BATCH"
54
+ cql = "BEGIN BATCH INSERT INTO other_keyspace_name.users (id) VALUES (?) UPDATE analytics.users SET name = ? WHERE \"id\" = ? APPLY BATCH"
55
55
  subject.call({
56
56
  keyspace_name: :analytics,
57
57
  modifications: [
@@ -6,7 +6,7 @@ describe Cassanity::ArgumentGenerators::ColumnFamilyDelete do
6
6
 
7
7
  describe "#call" do
8
8
  it "returns array of arguments" do
9
- cql = "DELETE FROM #{column_family_name} WHERE id = ?"
9
+ cql = "DELETE FROM #{column_family_name} WHERE \"id\" = ?"
10
10
  expected = [cql, '1']
11
11
  subject.call({
12
12
  column_family_name: column_family_name,
@@ -18,7 +18,7 @@ describe Cassanity::ArgumentGenerators::ColumnFamilyDelete do
18
18
 
19
19
  context "with :keyspace_name" do
20
20
  it "returns array of arguments" do
21
- cql = "DELETE FROM foo.#{column_family_name} WHERE id = ?"
21
+ cql = "DELETE FROM foo.#{column_family_name} WHERE \"id\" = ?"
22
22
  expected = [cql, '1']
23
23
  subject.call({
24
24
  keyspace_name: :foo,
@@ -30,9 +30,23 @@ describe Cassanity::ArgumentGenerators::ColumnFamilyDelete do
30
30
  end
31
31
  end
32
32
 
33
+ context "with single column" do
34
+ it "returns array of arguments only deleting specific column" do
35
+ cql = "DELETE foo FROM #{column_family_name} WHERE \"id\" = ?"
36
+ expected = [cql, '1']
37
+ subject.call({
38
+ column_family_name: column_family_name,
39
+ columns: :foo,
40
+ where: {
41
+ id: '1',
42
+ }
43
+ }).should eq(expected)
44
+ end
45
+ end
46
+
33
47
  context "with specific columns" do
34
48
  it "returns array of arguments only deleting specific columns" do
35
- cql = "DELETE foo, bar FROM #{column_family_name} WHERE id = ?"
49
+ cql = "DELETE foo, bar FROM #{column_family_name} WHERE \"id\" = ?"
36
50
  expected = [cql, '1']
37
51
  subject.call({
38
52
  column_family_name: column_family_name,
@@ -48,13 +62,13 @@ describe Cassanity::ArgumentGenerators::ColumnFamilyDelete do
48
62
  subject {
49
63
  described_class.new({
50
64
  where_clause: lambda { |args|
51
- [" WHERE id = ?", args.fetch(:where).fetch(:id)]
65
+ [" WHERE \"id\" = ?", args.fetch(:where).fetch(:id)]
52
66
  }
53
67
  })
54
68
  }
55
69
 
56
70
  it "uses where clause to get additional cql and bound variables" do
57
- cql = "DELETE FROM #{column_family_name} WHERE id = ?"
71
+ cql = "DELETE FROM #{column_family_name} WHERE \"id\" = ?"
58
72
  expected = [cql, '4']
59
73
  subject.call({
60
74
  column_family_name: column_family_name,
@@ -75,7 +89,7 @@ describe Cassanity::ArgumentGenerators::ColumnFamilyDelete do
75
89
  }
76
90
 
77
91
  it "uses using clause to get additional cql and bound variables" do
78
- cql = "DELETE FROM #{column_family_name} USING TTL = 500 WHERE id = ?"
92
+ cql = "DELETE FROM #{column_family_name} USING TTL = 500 WHERE \"id\" = ?"
79
93
  expected = [cql, '4']
80
94
  subject.call({
81
95
  column_family_name: column_family_name,
@@ -6,7 +6,7 @@ describe Cassanity::ArgumentGenerators::ColumnFamilyUpdate do
6
6
 
7
7
  describe "#call" do
8
8
  it "returns array of arguments" do
9
- cql = "UPDATE #{column_family_name} SET name = ? WHERE id = ?"
9
+ cql = "UPDATE #{column_family_name} SET name = ? WHERE \"id\" = ?"
10
10
  expected = [cql, 'New Name', '1']
11
11
  subject.call({
12
12
  column_family_name: column_family_name,
@@ -21,7 +21,7 @@ describe Cassanity::ArgumentGenerators::ColumnFamilyUpdate do
21
21
 
22
22
  context "with :keyspace_name" do
23
23
  it "returns array of arguments" do
24
- cql = "UPDATE foo.#{column_family_name} SET name = ? WHERE id = ?"
24
+ cql = "UPDATE foo.#{column_family_name} SET name = ? WHERE \"id\" = ?"
25
25
  expected = [cql, 'New Name', '1']
26
26
  subject.call({
27
27
  keyspace_name: :foo,
@@ -40,13 +40,13 @@ describe Cassanity::ArgumentGenerators::ColumnFamilyUpdate do
40
40
  subject {
41
41
  described_class.new({
42
42
  where_clause: lambda { |args|
43
- [" WHERE id = ?", args.fetch(:where).fetch(:id)]
43
+ [" WHERE \"id\" = ?", args.fetch(:where).fetch(:id)]
44
44
  }
45
45
  })
46
46
  }
47
47
 
48
48
  it "uses where clause to get additional cql and bound variables" do
49
- cql = "UPDATE #{column_family_name} SET name = ? WHERE id = ?"
49
+ cql = "UPDATE #{column_family_name} SET name = ? WHERE \"id\" = ?"
50
50
  expected = [cql, 'New Name', '4']
51
51
  subject.call({
52
52
  column_family_name: column_family_name,
@@ -70,7 +70,7 @@ describe Cassanity::ArgumentGenerators::ColumnFamilyUpdate do
70
70
  }
71
71
 
72
72
  it "uses set clause to get additional cql and bound variables" do
73
- cql = "UPDATE #{column_family_name} SET name = ? WHERE id = ?"
73
+ cql = "UPDATE #{column_family_name} SET name = ? WHERE \"id\" = ?"
74
74
  expected = [cql, 'New Name', '4']
75
75
  subject.call({
76
76
  column_family_name: column_family_name,
@@ -87,7 +87,7 @@ describe Cassanity::ArgumentGenerators::ColumnFamilyUpdate do
87
87
  context "with :using key" do
88
88
  it "returns array of arguments with cql including using" do
89
89
  millis = (Time.mktime(2012, 11, 1, 14, 9, 9).to_f * 1000).to_i
90
- cql = "UPDATE #{column_family_name} USING TTL 86400 AND TIMESTAMP #{millis} AND CONSISTENCY quorum SET name = ? WHERE id = ?"
90
+ cql = "UPDATE #{column_family_name} USING TTL 86400 AND TIMESTAMP #{millis} AND CONSISTENCY quorum SET name = ? WHERE \"id\" = ?"
91
91
  expected = [cql, 'New Name', '1']
92
92
  subject.call({
93
93
  column_family_name: column_family_name,
@@ -0,0 +1,45 @@
1
+ require 'helper'
2
+ require 'cassanity/argument_generators/columns'
3
+
4
+ describe Cassanity::ArgumentGenerators::Columns do
5
+ describe "#call" do
6
+ context "with no args" do
7
+ it "returns array of arguments for selecting all columns" do
8
+ cql = 'SELECT * FROM system.schema_columns'
9
+ expected = [cql]
10
+ subject.call.should eq(expected)
11
+ end
12
+ end
13
+
14
+ context "with keyspace" do
15
+ it "returns array of arguments for selecting all columns for keyspace" do
16
+ cql = 'SELECT * FROM system.schema_columns WHERE "keyspace" = ?'
17
+ expected = [cql, 'foo']
18
+ subject.call({
19
+ keyspace_name: 'foo',
20
+ }).should eq(expected)
21
+ end
22
+ end
23
+
24
+ context "with column family" do
25
+ it "returns array of arguments for selecting all columns for column family" do
26
+ cql = 'SELECT * FROM system.schema_columns WHERE "columnfamily" = ?'
27
+ expected = [cql, 'foo']
28
+ subject.call({
29
+ column_family_name: 'foo',
30
+ }).should eq(expected)
31
+ end
32
+ end
33
+
34
+ context "with keyspace and column family" do
35
+ it "returns array of arguments for selecting all columns for a column family in a keyspace" do
36
+ cql = 'SELECT * FROM system.schema_columns WHERE "keyspace" = ? AND "columnfamily" = ?'
37
+ expected = [cql, 'foo', 'bar']
38
+ subject.call({
39
+ keyspace_name: 'foo',
40
+ column_family_name: 'bar',
41
+ }).should eq(expected)
42
+ end
43
+ end
44
+ end
45
+ end
@@ -2,7 +2,7 @@ require 'helper'
2
2
  require 'cassanity/argument_generators/keyspace_create'
3
3
 
4
4
  describe Cassanity::ArgumentGenerators::KeyspaceCreate do
5
- let(:keyspace_name) { 'analytics' }
5
+ let(:keyspace_name) { :analytics }
6
6
 
7
7
  describe "#call" do
8
8
  context "only name" do
@@ -2,7 +2,7 @@ require 'helper'
2
2
  require 'cassanity/argument_generators/keyspace_drop'
3
3
 
4
4
  describe Cassanity::ArgumentGenerators::KeyspaceDrop do
5
- let(:keyspace_name) { 'analytics' }
5
+ let(:keyspace_name) { :analytics }
6
6
 
7
7
  describe "#call" do
8
8
  it "returns array of arguments" do
@@ -2,7 +2,7 @@ require 'helper'
2
2
  require 'cassanity/argument_generators/keyspace_use'
3
3
 
4
4
  describe Cassanity::ArgumentGenerators::KeyspaceUse do
5
- let(:keyspace_name) { 'analytics' }
5
+ let(:keyspace_name) { :analytics }
6
6
 
7
7
  describe "#call" do
8
8
  it "returns array of arguments" do
@@ -9,7 +9,7 @@ describe Cassanity::ArgumentGenerators::WhereClause do
9
9
  id: '1',
10
10
  }
11
11
  }).should eq([
12
- " WHERE id = ?",
12
+ ' WHERE "id" = ?',
13
13
  '1',
14
14
  ])
15
15
  end
@@ -34,7 +34,7 @@ describe Cassanity::ArgumentGenerators::WhereClause do
34
34
  id: '1',
35
35
  }
36
36
  }).should eq([
37
- " WHERE bucket = ? AND id = ?",
37
+ ' WHERE "bucket" = ? AND "id" = ?',
38
38
  '2012',
39
39
  '1',
40
40
  ])
@@ -2,6 +2,13 @@ require 'helper'
2
2
  require 'cassanity/client'
3
3
 
4
4
  describe Cassanity::Client do
5
+ let(:driver) { double('Driver') }
6
+
7
+ before do
8
+ # Ensure that we never hit cassandra for real here.
9
+ CassandraCQL::Database.stub(:new => driver)
10
+ end
11
+
5
12
  describe "#initialize" do
6
13
  it "passes arguments to cassandra cql database instance" do
7
14
  CassandraCQL::Database.should_receive(:new).
@@ -72,7 +79,7 @@ describe Cassanity::Client do
72
79
  and_return(driver)
73
80
 
74
81
  Cassanity::Executors::CassandraCql.should_receive(:new).
75
- with(client: driver, instrumenter: instrumenter).
82
+ with(hash_including(driver: driver, instrumenter: instrumenter)).
76
83
  and_return(executor)
77
84
 
78
85
  described_class.new('localhost:1234', instrumenter: instrumenter)
@@ -80,7 +87,7 @@ describe Cassanity::Client do
80
87
 
81
88
  it "sets cassandra cql database instance as driver" do
82
89
  client = described_class.new
83
- client.driver.should be_instance_of(CassandraCQL::Database)
90
+ client.driver.should be_instance_of(driver.class)
84
91
  end
85
92
 
86
93
  it "builds driver, executor and connection" do
@@ -91,7 +98,7 @@ describe Cassanity::Client do
91
98
  CassandraCQL::Database.should_receive(:new).and_return(driver)
92
99
 
93
100
  Cassanity::Executors::CassandraCql.should_receive(:new).
94
- with(hash_including(client: driver)).
101
+ with(hash_including(driver: driver)).
95
102
  and_return(executor)
96
103
 
97
104
  Cassanity::Connection.should_receive(:new).
@@ -2,7 +2,7 @@ require 'helper'
2
2
  require 'cassanity/column_family'
3
3
 
4
4
  describe Cassanity::ColumnFamily do
5
- let(:column_family_name) { 'analytics' }
5
+ let(:column_family_name) { :analytics }
6
6
  let(:keyspace_name) { 'foo' }
7
7
 
8
8
  let(:keyspace) {
@@ -81,6 +81,15 @@ describe Cassanity::ColumnFamily do
81
81
  end
82
82
  end
83
83
 
84
+ context "with string name" do
85
+ it "converts name to symbol" do
86
+ column_family = described_class.new(required_arguments.merge({
87
+ name: 'foo',
88
+ }))
89
+ column_family.name.should be(:foo)
90
+ end
91
+ end
92
+
84
93
  describe "#schema" do
85
94
  it "returns schema if set" do
86
95
  described_class.new(required_arguments.merge({
@@ -100,8 +109,12 @@ describe Cassanity::ColumnFamily do
100
109
  executor.should_receive(:call).with({
101
110
  command: :column_families,
102
111
  arguments: {keyspace_name: keyspace.name},
112
+ transformer_arguments: {keyspace: keyspace},
103
113
  }).and_return([
104
- {'columnfamily' => column_family_name},
114
+ Cassanity::ColumnFamily.new({
115
+ name: column_family_name,
116
+ keyspace: keyspace,
117
+ })
105
118
  ])
106
119
 
107
120
  subject.send(method_name).should be_true
@@ -111,8 +124,12 @@ describe Cassanity::ColumnFamily do
111
124
  executor.should_receive(:call).with({
112
125
  command: :column_families,
113
126
  arguments: {keyspace_name: keyspace.name},
127
+ transformer_arguments: {keyspace: keyspace},
114
128
  }).and_return([
115
- {'columnfamily' => 'boo'},
129
+ Cassanity::ColumnFamily.new({
130
+ name: 'boo',
131
+ keyspace: keyspace,
132
+ })
116
133
  ])
117
134
 
118
135
  subject.send(method_name).should be_false
@@ -0,0 +1,76 @@
1
+ require 'helper'
2
+ require 'cassanity/column_family'
3
+
4
+ describe Cassanity::Column do
5
+ let(:name) { :age }
6
+ let(:type) { :int }
7
+ let(:column_family) { double('Column Family') }
8
+
9
+ let(:required_arguments) {
10
+ {
11
+ name: name,
12
+ type: type,
13
+ column_family: column_family,
14
+ }
15
+ }
16
+
17
+ subject { described_class.new(required_arguments) }
18
+
19
+ it { should respond_to(:name) }
20
+ it { should respond_to(:type) }
21
+ it { should respond_to(:column_family) }
22
+
23
+ describe "#initialize" do
24
+ it "sets name" do
25
+ subject.name.should eq(name)
26
+ end
27
+
28
+ it "sets type" do
29
+ subject.type.should eq(type)
30
+ end
31
+
32
+ it "sets column_family" do
33
+ subject.column_family.should eq(column_family)
34
+ end
35
+
36
+ [:name, :type, :column_family].each do |key|
37
+ it "raises error without :#{key} key" do
38
+ args = required_arguments.reject { |k, v| k == key }
39
+ expect { described_class.new(args) }.to raise_error(KeyError)
40
+ end
41
+ end
42
+ end
43
+
44
+ context "initializing with string name" do
45
+ it "sets name to symbol" do
46
+ instance = described_class.new(required_arguments.merge(name: 'foo'))
47
+ instance.name.should be(:foo)
48
+ end
49
+ end
50
+
51
+ context "initializing with long cassandra type" do
52
+ described_class::Types.each do |long, short|
53
+ it "converts #{long} to #{short}" do
54
+ instance = described_class.new(required_arguments.merge(type: long))
55
+ instance.type.should eq(short)
56
+ end
57
+ end
58
+ end
59
+
60
+ context "initializing with some unknown long type" do
61
+ it "sets does not change type" do
62
+ instance = described_class.new(required_arguments.merge(type: 'foo.bar.String'))
63
+ instance.type.should eq('foo.bar.String')
64
+ end
65
+ end
66
+
67
+ describe "#inspect" do
68
+ it "return representation" do
69
+ result = subject.inspect
70
+ result.should match(/#{described_class}/)
71
+ result.should match(/name=/)
72
+ result.should match(/type=/)
73
+ result.should match(/column_family=/)
74
+ end
75
+ end
76
+ end