cequel 1.0.0.rc1 → 1.0.0.rc2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/lib/cequel.rb +18 -0
  3. data/lib/cequel/errors.rb +8 -4
  4. data/lib/cequel/metal.rb +14 -0
  5. data/lib/cequel/metal/batch.rb +21 -11
  6. data/lib/cequel/metal/batch_manager.rb +74 -0
  7. data/lib/cequel/metal/cql_row_specification.rb +19 -6
  8. data/lib/cequel/metal/data_set.rb +400 -163
  9. data/lib/cequel/metal/deleter.rb +45 -11
  10. data/lib/cequel/metal/incrementer.rb +23 -10
  11. data/lib/cequel/metal/inserter.rb +19 -6
  12. data/lib/cequel/metal/keyspace.rb +82 -159
  13. data/lib/cequel/metal/logger.rb +71 -0
  14. data/lib/cequel/metal/logging.rb +47 -0
  15. data/lib/cequel/metal/new_relic_instrumentation.rb +26 -0
  16. data/lib/cequel/metal/row.rb +36 -10
  17. data/lib/cequel/metal/row_specification.rb +21 -8
  18. data/lib/cequel/metal/statement.rb +30 -6
  19. data/lib/cequel/metal/updater.rb +89 -12
  20. data/lib/cequel/metal/writer.rb +23 -14
  21. data/lib/cequel/record.rb +52 -6
  22. data/lib/cequel/record/association_collection.rb +13 -6
  23. data/lib/cequel/record/associations.rb +146 -54
  24. data/lib/cequel/record/belongs_to_association.rb +34 -7
  25. data/lib/cequel/record/bound.rb +69 -12
  26. data/lib/cequel/record/bulk_writes.rb +29 -1
  27. data/lib/cequel/record/callbacks.rb +22 -6
  28. data/lib/cequel/record/collection.rb +273 -36
  29. data/lib/cequel/record/configuration_generator.rb +5 -0
  30. data/lib/cequel/record/data_set_builder.rb +86 -0
  31. data/lib/cequel/record/dirty.rb +11 -8
  32. data/lib/cequel/record/errors.rb +38 -4
  33. data/lib/cequel/record/has_many_association.rb +42 -9
  34. data/lib/cequel/record/lazy_record_collection.rb +39 -10
  35. data/lib/cequel/record/mass_assignment.rb +14 -6
  36. data/lib/cequel/record/persistence.rb +157 -20
  37. data/lib/cequel/record/properties.rb +147 -24
  38. data/lib/cequel/record/railtie.rb +15 -2
  39. data/lib/cequel/record/record_set.rb +504 -75
  40. data/lib/cequel/record/schema.rb +77 -13
  41. data/lib/cequel/record/scoped.rb +16 -11
  42. data/lib/cequel/record/secondary_indexes.rb +42 -6
  43. data/lib/cequel/record/tasks.rb +2 -1
  44. data/lib/cequel/record/validations.rb +51 -11
  45. data/lib/cequel/schema.rb +9 -0
  46. data/lib/cequel/schema/column.rb +172 -33
  47. data/lib/cequel/schema/create_table_dsl.rb +62 -31
  48. data/lib/cequel/schema/keyspace.rb +106 -7
  49. data/lib/cequel/schema/migration_validator.rb +128 -0
  50. data/lib/cequel/schema/table.rb +183 -20
  51. data/lib/cequel/schema/table_property.rb +92 -34
  52. data/lib/cequel/schema/table_reader.rb +45 -15
  53. data/lib/cequel/schema/table_synchronizer.rb +101 -43
  54. data/lib/cequel/schema/table_updater.rb +114 -19
  55. data/lib/cequel/schema/table_writer.rb +31 -13
  56. data/lib/cequel/schema/update_table_dsl.rb +71 -40
  57. data/lib/cequel/type.rb +214 -53
  58. data/lib/cequel/util.rb +6 -9
  59. data/lib/cequel/version.rb +2 -1
  60. data/spec/examples/record/associations_spec.rb +12 -12
  61. data/spec/examples/record/persistence_spec.rb +5 -5
  62. data/spec/examples/record/record_set_spec.rb +62 -50
  63. data/spec/examples/schema/table_synchronizer_spec.rb +37 -11
  64. data/spec/examples/schema/table_updater_spec.rb +3 -3
  65. data/spec/examples/spec_helper.rb +2 -11
  66. data/spec/examples/type_spec.rb +3 -3
  67. metadata +23 -4
  68. data/lib/cequel/new_relic_instrumentation.rb +0 -22
@@ -1,33 +1,96 @@
1
1
  module Cequel
2
-
3
2
  module Record
4
-
3
+ #
4
+ # `Cequel::Record` implementations define their own schema in their class
5
+ # definitions. As well as defining attributes on record instances, the
6
+ # column definitions in {Properties} allow a `Cequel::Record` to have a
7
+ # precise internal represntation of its representation as a CQL3 table
8
+ # schema. Further, it is able to check this representation against the
9
+ # actual table defined in Cassandra (if any), and create or modify the
10
+ # schema in Cassandra to match what's defined in code.
11
+ #
12
+ # All the interesting stuff is in the {ClassMethods}.
13
+ #
14
+ # @since 1.0.0
15
+ #
5
16
  module Schema
6
-
7
17
  extend ActiveSupport::Concern
8
18
  extend Forwardable
9
19
 
10
20
  included do
11
- class_attribute :table_name, :instance_writer => false
21
+ class_attribute :table_name, instance_writer: false
12
22
  self.table_name = name.tableize.to_sym unless name.nil?
13
23
  end
14
24
 
25
+ #
26
+ # Methods available on {Record} class singletons to introspect and modify
27
+ # the schema defined in the database
28
+ #
15
29
  module ClassMethods
30
+ #
31
+ # @!attr table_name
32
+ # @return [Symbol] name of the CQL table that backs this record class
33
+ #
34
+
16
35
  extend Forwardable
17
36
 
18
- def_delegators :table_schema, :columns, :key_columns, :key_column_names,
19
- :partition_key_columns, :clustering_columns, :compact_storage?
37
+ #
38
+ # @!attribute [r] columns
39
+ # (see Cequel::Schema::Table#columns)
40
+ #
41
+ # @!attribute [r] key_columns
42
+ # (see Cequel::Schema::Table#key_columns)
43
+ #
44
+ # @!attribute [r] key_column_names
45
+ # (see Cequel::Schema::Table#key_column_names)
46
+ #
47
+ # @!attribute [r] partition_key_columns
48
+ # (see Cequel::Schema::Table#partition_key_columns)
49
+ #
50
+ # @!attribute [r] clustering_columns
51
+ # (see Cequel::Schema::Table#clustering_columns)
52
+ #
53
+ # @!method compact_storage?
54
+ # (see Cequel::Schema::Table#compact_storage?)
55
+ #
56
+ def_delegators :table_schema, :columns, :key_columns,
57
+ :key_column_names, :partition_key_columns,
58
+ :clustering_columns, :compact_storage?
59
+ #
60
+ # @!method reflect_on_column(name)
61
+ # (see Cequel::Schema::Table#column)
62
+ #
20
63
  def_delegator :table_schema, :column, :reflect_on_column
21
64
 
65
+ #
66
+ # Read the current schema assigned to this record's table from
67
+ # Cassandra, and make any necessary modifications (including creating
68
+ # the table for the first time) so that it matches the schema defined
69
+ # in the record definition
70
+ #
71
+ # @raise (see Schema::TableSynchronizer.apply)
72
+ # @return [void]
73
+ #
22
74
  def synchronize_schema
23
- Cequel::Schema::TableSynchronizer.
24
- apply(connection, read_schema, table_schema)
75
+ Cequel::Schema::TableSynchronizer
76
+ .apply(connection, read_schema, table_schema)
25
77
  end
26
78
 
79
+ #
80
+ # Read the current state of this record's table in Cassandra from the
81
+ # database.
82
+ #
83
+ # @return [Schema::Table] the current schema assigned to this record's
84
+ # table in the database
85
+ #
27
86
  def read_schema
28
87
  connection.schema.read_table(table_name)
29
88
  end
30
89
 
90
+ #
91
+ # @return [Schema::Table] the schema as defined by the columns
92
+ # specified in the class definition
93
+ #
31
94
  def table_schema
32
95
  @table_schema ||= Cequel::Schema::Table.new(table_name)
33
96
  end
@@ -36,7 +99,11 @@ module Cequel
36
99
 
37
100
  def key(name, type, options = {})
38
101
  super
39
- table_schema.add_key(name, type)
102
+ if options[:partition]
103
+ table_schema.add_partition_key(name, type)
104
+ else
105
+ table_schema.add_key(name, type)
106
+ end
40
107
  end
41
108
 
42
109
  def column(name, type, options = {})
@@ -66,15 +133,12 @@ module Cequel
66
133
  def compact_storage
67
134
  table_schema.compact_storage = true
68
135
  end
69
-
70
136
  end
71
137
 
72
138
  protected
139
+
73
140
  def_delegator 'self.class', :table_schema
74
141
  protected :table_schema
75
-
76
142
  end
77
-
78
143
  end
79
-
80
144
  end
@@ -1,24 +1,31 @@
1
1
  module Cequel
2
-
3
2
  module Record
4
-
3
+ #
4
+ # All of the instance methods of {RecordSet} are also available as class
5
+ # methods on {Record} implementations.
6
+ #
7
+ # @since 0.1.0
8
+ #
5
9
  module Scoped
6
-
7
10
  extend ActiveSupport::Concern
8
11
 
12
+ #
13
+ # Scoping-related methods for {Record} classes
14
+ #
9
15
  module ClassMethods
10
-
11
16
  extend Forwardable
12
17
 
13
18
  def_delegators :current_scope,
14
- *(RecordSet.public_instance_methods(false) +
15
- BulkWrites.public_instance_methods -
16
- Object.instance_methods)
19
+ *(RecordSet.public_instance_methods(false) +
20
+ BulkWrites.public_instance_methods -
21
+ Object.instance_methods)
17
22
 
23
+ # @private
18
24
  def current_scope
19
25
  delegating_scope || RecordSet.new(self)
20
26
  end
21
27
 
28
+ # @private
22
29
  def with_scope(record_set)
23
30
  previous_scope = delegating_scope
24
31
  self.delegating_scope = record_set
@@ -40,16 +47,14 @@ module Cequel
40
47
  def delegating_scope_key
41
48
  @delegating_scope_key ||= :"#{name}::delegating_scope"
42
49
  end
43
-
44
50
  end
45
51
 
52
+ private
53
+
46
54
  def initialize_new_record(*)
47
55
  super
48
56
  @attributes.merge!(self.class.current_scope.scoped_key_attributes)
49
57
  end
50
-
51
58
  end
52
-
53
59
  end
54
-
55
60
  end
@@ -1,9 +1,48 @@
1
1
  module Cequel
2
-
3
2
  module Record
4
-
3
+ #
4
+ # Data columns may be given secondary indexes. This allows you to query the
5
+ # table for records where the indexed column contains a single value.
6
+ # Secondary indexes are not nearly as flexible as primary keys: you cannot
7
+ # query for multiple values or for ranges of values. You also cannot
8
+ # combine a secondary index restriction with a primary key restriction in
9
+ # the same query, nor can you combine more than one secondary index
10
+ # restrictions in the same query.
11
+ #
12
+ # If a column is given a secondary index, magic finder methods `find_by_*`,
13
+ # `find_all_by_*`, and `with_*` are added to the class singleton. See below
14
+ # for an example.
15
+ #
16
+ # Secondary indexes are fairly expensive for Cassandra and should only be
17
+ # defined where needed.
18
+ #
19
+ # @example Defining a secondary index
20
+ # class Post
21
+ # belongs_to :blog
22
+ # key :id, :timeuuid, auto: true
23
+ # column :title, :text
24
+ # column :body, :text
25
+ # column :author_id, :uuid, index: true # this column has a secondary
26
+ # # index
27
+ # end
28
+ #
29
+ # @example Using a secondary index
30
+ # # return the first record with the author_id
31
+ # Post.find_by_author_id(id)
32
+ #
33
+ # # return an Array of all records with the author_id
34
+ # Post.find_all_by_author_id(id)
35
+ #
36
+ # # return a RecordSet scoped to the author_id
37
+ # Post.with_author_id(id)
38
+ #
39
+ # # same as with_author_id
40
+ # Post.where(:author_id, id)
41
+ #
42
+ # @since 1.0.0
43
+ #
5
44
  module SecondaryIndexes
6
-
45
+ # @private
7
46
  def column(name, type, options = {})
8
47
  super
9
48
  name = name.to_sym
@@ -23,9 +62,6 @@ module Cequel
23
62
  RUBY
24
63
  end
25
64
  end
26
-
27
65
  end
28
-
29
66
  end
30
-
31
67
  end
@@ -13,7 +13,8 @@ namespace :cequel do
13
13
  end
14
14
  end
15
15
 
16
- desc "Synchronize all models defined in `app/models' with Cassandra database schema"
16
+ desc "Synchronize all models defined in `app/models' with Cassandra " \
17
+ "database schema"
17
18
  task :migrate => :environment do
18
19
  watch_stack = ActiveSupport::Dependencies::WatchStack.new
19
20
 
@@ -1,9 +1,25 @@
1
1
  module Cequel
2
-
3
2
  module Record
4
-
3
+ #
4
+ # {Record} classes can define validations that are run before saving a
5
+ # record instance.
6
+ #
7
+ # @example Validations
8
+ # class User
9
+ # include Cequel::Record
10
+ #
11
+ # key :login, :text
12
+ # column :email, :text
13
+ #
14
+ # validates :email, presence: true, format: RFC822::EMAIL
15
+ # end
16
+ #
17
+ # @see http://api.rubyonrails.org/classes/ActiveModel/Validations.html
18
+ # ActiveModel::Validations
19
+ #
20
+ # @since 0.1.0
21
+ #
5
22
  module Validations
6
-
7
23
  extend ActiveSupport::Concern
8
24
 
9
25
  included do
@@ -12,39 +28,63 @@ module Cequel
12
28
  alias_method_chain :valid?, :callbacks
13
29
  end
14
30
 
31
+ #
32
+ # Validation-related methods exposed on Record class singletons
33
+ #
15
34
  module ClassMethods
16
-
35
+ #
36
+ # Attempt to create a new record, or raise an exception otherwise
37
+ #
38
+ # @param (see Persistence::ClassMethods#create)
39
+ # @yieldparam (see Persistence::ClassMethods#create)
40
+ # @return (see Persistence::ClassMethods#create)
41
+ # @raise (see Validations#save!)
42
+ #
17
43
  def create!(attributes = {}, &block)
18
44
  new(attributes, &block).save!
19
45
  end
20
-
21
46
  end
22
47
 
48
+ # @private
23
49
  def save(options = {})
24
50
  validate = options.fetch(:validate, true)
25
51
  options.delete(:validate)
26
52
  (!validate || valid?) && super
27
53
  end
28
54
 
29
- def save!(options = {})
55
+ #
56
+ # Attempt to save the record, or raise an exception if there is a
57
+ # validation error
58
+ #
59
+ # @param (see Persistence#save)
60
+ # @return [Record] self
61
+ # @raise [RecordInvalid] if there are validation errors
62
+ #
63
+ def save!(attributes = {})
30
64
  tap do
31
- unless save(options)
32
- raise RecordInvalid, errors.full_messages.join("; ")
65
+ unless save(attributes)
66
+ fail RecordInvalid, errors.full_messages.join("; ")
33
67
  end
34
68
  end
35
69
  end
36
70
 
71
+ #
72
+ # Set the given attributes and attempt to save, raising an exception if
73
+ # there is a validation error
74
+ #
75
+ # @param (see Persistence#update_attributes)
76
+ # @return (see #save!)
77
+ # @raise (see #save!)
37
78
  def update_attributes!(attributes)
38
79
  self.attributes = attributes
39
80
  save!
40
81
  end
41
82
 
83
+ private
84
+
42
85
  def valid_with_callbacks?
43
86
  run_callbacks(:validation) { valid_without_callbacks? }
44
87
  end
45
-
46
88
  end
47
-
48
89
  end
49
-
50
90
  end
data/lib/cequel/schema.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'cequel/schema/column'
2
2
  require 'cequel/schema/create_table_dsl'
3
3
  require 'cequel/schema/keyspace'
4
+ require 'cequel/schema/migration_validator'
4
5
  require 'cequel/schema/table'
5
6
  require 'cequel/schema/table_property'
6
7
  require 'cequel/schema/table_reader'
@@ -10,6 +11,14 @@ require 'cequel/schema/table_writer'
10
11
  require 'cequel/schema/update_table_dsl'
11
12
 
12
13
  module Cequel
14
+ #
15
+ # The Schema module provides full read/write access to keyspace and table
16
+ # schemas defined in Cassandra.
17
+ #
18
+ # @see Schema::Keyspace
19
+ #
20
+ # @since 1.0.0
21
+ #
13
22
  module Schema
14
23
  end
15
24
  end
@@ -1,155 +1,294 @@
1
1
  module Cequel
2
-
3
2
  module Schema
4
-
3
+ #
4
+ # Represents a column definition in a table schema.
5
+ #
6
+ # @abstract
7
+ #
5
8
  class Column
6
-
7
- attr_reader :name, :type
8
-
9
+ # @return [Symbol] the name of the column
10
+ attr_reader :name
11
+ # @return [Type] the type of the column
12
+ attr_reader :type
13
+
14
+ #
15
+ # @param name [Symbol] the name of the column
16
+ # @param type [Type] the type of the column
17
+ #
9
18
  def initialize(name, type)
10
19
  @name, @type = name, type
11
20
  end
12
21
 
22
+ #
23
+ # @return [Boolean] true if this is a key column
24
+ #
25
+ # @see
26
+ # http://www.datastax.com/documentation/cql/3.0/webhelp/index.html#cql/ddl/../../cassandra/glossary/gloss_glossary.html
27
+ # The CQL3 glossary
28
+ #
13
29
  def key?
14
30
  partition_key? || clustering_column?
15
31
  end
16
32
 
33
+ #
34
+ # @return [Boolean] true if this is a partition key column
35
+ #
36
+ # @see
37
+ # http://www.datastax.com/documentation/cql/3.0/webhelp/index.html#cql/ddl/../../cassandra/glossary/gloss_glossary.html
38
+ # The CQL3 glossary
39
+ #
17
40
  def partition_key?
18
41
  false
19
42
  end
20
43
 
21
- def type?(type_in)
22
- type.is_a?(type_in)
23
- end
24
-
44
+ #
45
+ # @return [Boolean] true if this is a clustering column
46
+ #
47
+ # @see
48
+ # http://www.datastax.com/documentation/cql/3.0/webhelp/index.html#cql/ddl/../../cassandra/glossary/gloss_glossary.html
49
+ # The CQL3 glossary
50
+ #
25
51
  def clustering_column?
26
52
  false
27
53
  end
28
54
 
55
+ #
56
+ # @return [Boolean] true if this is a data column
57
+ #
58
+ # @see
59
+ # http://www.datastax.com/documentation/cql/3.0/webhelp/index.html#cql/ddl/../../cassandra/glossary/gloss_glossary.html
60
+ # The CQL3 glossary
61
+ #
29
62
  def data_column?
30
63
  !key?
31
64
  end
32
65
 
33
- def to_cql
34
- "#{@name} #{@type}"
66
+ #
67
+ # @return [Boolean] true if this is a collection column
68
+ #
69
+ def collection_column?
70
+ false
35
71
  end
36
72
 
73
+ #
74
+ # @param type_in [Symbol,Type] type to check against
75
+ # @return [Boolean] true if this column has the type given by `type_in`
76
+ #
77
+ def type?(type_in)
78
+ type == Type[type_in]
79
+ end
80
+
81
+ #
82
+ # @param value the value to cast
83
+ # @return the value cast to the appropriate type for this column
84
+ #
85
+ # @api private
86
+ #
37
87
  def cast(value)
38
88
  @type.cast(value)
39
89
  end
40
90
 
91
+ #
92
+ # @return [String] a CQL fragment representing this column in a table
93
+ # definition
94
+ #
95
+ # @api private
96
+ #
97
+ def to_cql
98
+ "#{@name} #{@type}"
99
+ end
100
+
101
+ #
102
+ # @param other [Column] a column object
103
+ # @return [Boolean] true if this column has the same CQL representation
104
+ # as `other` column
105
+ #
41
106
  def ==(other)
42
107
  to_cql == other.to_cql
43
108
  end
44
109
 
110
+ #
111
+ # @return [String] the column's name
112
+ #
45
113
  def to_s
46
114
  name
47
115
  end
48
116
 
117
+ #
118
+ # @return [String] human-readable representation of this column
119
+ #
49
120
  def inspect
50
121
  %Q(#<#{self.class.name}: #{to_cql}>)
51
122
  end
52
-
53
123
  end
54
124
 
125
+ #
126
+ # A partition key column
127
+ #
55
128
  class PartitionKey < Column
56
-
129
+ #
130
+ # (see Column#partition_key?)
131
+ #
57
132
  def partition_key?
58
133
  true
59
134
  end
60
-
61
135
  end
62
136
 
137
+ #
138
+ # A clustering column
139
+ #
63
140
  class ClusteringColumn < Column
64
-
141
+ #
142
+ # @return [:asc,:desc] whether rows are ordered by ascending or
143
+ # descending values in this column
144
+ #
65
145
  attr_reader :clustering_order
66
146
 
147
+ #
148
+ # @param (see Column#initialize)
149
+ # @param clustering_order [:asc,:desc] ascending or descending order for
150
+ # this column
151
+ #
67
152
  def initialize(name, type, clustering_order = nil)
68
153
  super(name, type)
69
154
  @clustering_order = (clustering_order || :asc).to_sym
70
155
  end
71
156
 
72
- def clustering_order_cql
73
- "#{@name} #{@clustering_order}"
74
- end
75
-
157
+ #
158
+ # (see Column#clustering_column?)
159
+ #
76
160
  def clustering_column?
77
161
  true
78
162
  end
79
163
 
164
+ # @private
165
+ def clustering_order_cql
166
+ "#{@name} #{@clustering_order}"
167
+ end
80
168
  end
81
169
 
170
+ #
171
+ # A scalar data column
172
+ #
82
173
  class DataColumn < Column
83
-
174
+ #
175
+ # @return [Symbol] name of the secondary index applied to this column, if
176
+ # any
177
+ #
84
178
  attr_reader :index_name
85
179
 
180
+ #
181
+ # @param (see Column#initialize)
182
+ # @param index_name [Symbol] name this column's secondary index
183
+ #
86
184
  def initialize(name, type, index_name = nil)
87
185
  super(name, type)
88
186
  @index_name = index_name
89
187
  end
90
188
 
189
+ #
190
+ # @return [Boolean] true if this column has a secondary index
191
+ #
91
192
  def indexed?
92
193
  !!@index_name
93
194
  end
94
-
95
195
  end
96
196
 
197
+ #
198
+ # A collection column (list, set, or map)
199
+ #
200
+ # @abstract
201
+ #
97
202
  class CollectionColumn < Column
203
+ # (see Column#collection_column?)
204
+ def collection_column?
205
+ true
206
+ end
98
207
 
208
+ # (see DataColumn#indexed?)
99
209
  def indexed?
100
210
  false
101
211
  end
102
-
103
212
  end
104
213
 
214
+ #
215
+ # A List column
216
+ #
217
+ # @see http://www.datastax.com/documentation/cql/3.0/webhelp/index.html#cql/cql_using/use_collections_c.html#task_ds_lqp_krj_zj CQL documentation for the list type
218
+ #
105
219
  class List < CollectionColumn
106
-
220
+ # (see Column#to_cql)
107
221
  def to_cql
108
222
  "#{@name} LIST <#{@type}>"
109
223
  end
110
224
 
225
+ #
226
+ # @return [Array] array with elements cast to correct type for column
227
+ #
111
228
  def cast(value)
112
229
  value.map { |element| @type.cast(element) }
113
230
  end
114
-
115
231
  end
116
232
 
233
+ #
234
+ # A Set column
235
+ #
236
+ # @see
237
+ # http://www.datastax.com/documentation/cql/3.0/webhelp/index.html#cql/cql_using/use_collections_c.html#task_ds_agt_3kj_zj
238
+ # CQL documentation for set columns
239
+ #
117
240
  class Set < CollectionColumn
118
-
241
+ # (see Column#to_cql)
119
242
  def to_cql
120
243
  "#{@name} SET <#{@type}>"
121
244
  end
122
245
 
246
+ #
247
+ # @param (see Column#cast)
248
+ # @return [::Set] set with elements cast to correct type for column
249
+ #
123
250
  def cast(value)
124
- value.each_with_object(::Set[]) do |element, set|
125
- set << @type.cast(element)
126
- end
251
+ value.to_set { |element| @type.cast(element) }
127
252
  end
128
-
129
253
  end
130
254
 
255
+ #
256
+ # A Map column
257
+ #
258
+ # @see
259
+ # http://www.datastax.com/documentation/cql/3.0/webhelp/index.html#cql/cql_using/use_collections_c.html#task_ds_cvq_kcl_zj
260
+ # CQL documentation for map columns
261
+ #
131
262
  class Map < CollectionColumn
132
-
263
+ # @return [Type] the type of keys in this map
133
264
  attr_reader :key_type
134
265
  alias_method :value_type, :type
135
266
 
267
+ #
268
+ # @param name [Symbol] name of this column
269
+ # @param key_type [Type] type of the keys in the map
270
+ # @param value_type [Type] type of the values in the map
271
+ #
136
272
  def initialize(name, key_type, value_type)
137
273
  super(name, value_type)
138
274
  @key_type = key_type
139
275
  end
140
276
 
277
+ # (see Column#to_cql)
141
278
  def to_cql
142
279
  "#{@name} MAP <#{@key_type}, #{@type}>"
143
280
  end
144
281
 
282
+ #
283
+ # @param (see Column#cast)
284
+ # @return [Hash] hash with keys and values cast to correct type for
285
+ # column
286
+ #
145
287
  def cast(value)
146
288
  value.each_with_object({}) do |(key, element), hash|
147
289
  hash[@key_type.cast(key)] = @type.cast(element)
148
290
  end
149
291
  end
150
-
151
292
  end
152
-
153
293
  end
154
-
155
294
  end