cassanity 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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