cequel 1.0.0.rc1 → 1.0.0.rc2

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 (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