Module: Cassie::Model::ClassMethods
- Defined in:
- lib/cassie/model.rb
Instance Method Summary collapse
-
#batch ⇒ Object
All insert, update, and delete calls within the block will be sent as a single batch to Cassandra.
-
#column(name, type, as: nil) ⇒ Object
Define a column name and type from the table.
-
#column_name(name_or_alias) ⇒ Object
Returns the internal column name after resolving any aliases.
-
#column_names ⇒ Object
Returns an array of the defined column names as symbols.
-
#connection ⇒ Object
Returns the Cassie instance used to communicate with Cassandra.
-
#count(where = nil) ⇒ Object
Return the count of rows in the table.
-
#create(attributes) ⇒ Object
Returns a newly created record.
-
#create!(attributes) ⇒ Object
Returns a newly created record or raises an ActiveRecord::RecordInvalid error if the record is not valid.
-
#delete_all(key_hash) ⇒ Object
Delete all rows from the table that match the key hash.
-
#find(where) ⇒ Object
Find a single record that matches the
whereargument. -
#find!(where) ⇒ Object
Find a single record that matches the
whereargument or raise an ActiveRecord::RecordNotFound error if none is found. -
#find_all(where:, select: nil, order: nil, limit: nil, options: nil) ⇒ Object
Find all records.
-
#full_table_name ⇒ Object
Return the full table name including the keyspace.
-
#keyspace ⇒ Object
Return the keyspace name where the table is located.
-
#keyspace=(name) ⇒ Object
Set the keyspace for the table.
-
#offset_to_id(key, offset, order: nil, batch_size: 1000, min: nil, max: nil) ⇒ Object
Since Cassandra doesn’t support offset we need to find the order key of record at the specified the offset.
-
#ordering_key(name, order) ⇒ Object
Define and ordering key for the table.
-
#primary_key ⇒ Object
Return an array of column names for the table primary key.
-
#primary_key=(value) ⇒ Object
Set the primary key for the table.
Instance Method Details
#batch ⇒ Object
All insert, update, and delete calls within the block will be sent as a single batch to Cassandra.
271 272 273 274 275 |
# File 'lib/cassie/model.rb', line 271 def batch connection.batch do yield end end |
#column(name, type, as: nil) ⇒ Object
Define a column name and type from the table. Columns must be defined in order to be used. This method will handle defining the getter and setter methods as well.
The type specified must be a valid CQL data type.
Because Cassandra stores column names with each row it is beneficial to use very short column names. You can specify the :as option to define a more human readable version. This will add the appropriate getter and setter methods as well as allow you to use the alias name in the methods that take an attributes hash.
Defining a column will also define getter and setter methods for both the column name and the alias name (if specified). So ‘column :i, :int, as: :id` will define the methods `i`, `i=`, `id`, and `id=`.
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/cassie/model.rb', line 69 def column(name, type, as: nil) name = name.to_sym type_class = nil begin type_class = "Cassandra::Types::#{type.to_s.downcase.classify}".constantize rescue NameError raise ArgumentError.new("#{type.inspect} is not an allowed Cassandra type") end self._columns = _columns.merge(name => type_class) self._column_aliases = self._column_aliases.merge(name => name) define_method("#{name}="){ |value| instance_variable_set(:"@#{name}", self.class.send(:coerce, value, type_class)) } attr_reader name if as && as.to_s != name.to_s self._column_aliases = self._column_aliases.merge(as => name) define_method(as){ send(name) } define_method("#{as}="){|value| send("#{name}=", value) } end end |
#column_name(name_or_alias) ⇒ Object
Returns the internal column name after resolving any aliases.
96 97 98 |
# File 'lib/cassie/model.rb', line 96 def column_name(name_or_alias) name = _column_aliases[name_or_alias] || name_or_alias end |
#column_names ⇒ Object
Returns an array of the defined column names as symbols.
91 92 93 |
# File 'lib/cassie/model.rb', line 91 def column_names _columns.keys end |
#connection ⇒ Object
Returns the Cassie instance used to communicate with Cassandra.
278 279 280 |
# File 'lib/cassie/model.rb', line 278 def connection Cassie.instance end |
#count(where = nil) ⇒ Object
Return the count of rows in the table. If the where argument is specified then it will be added as the WHERE clause.
222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 |
# File 'lib/cassie/model.rb', line 222 def count(where = nil) = nil if where.is_a?(Hash) && where.include?(:options) where = where.dup = where.delete(:options) end cql = "SELECT COUNT(*) FROM #{self.full_table_name}" values = nil if where where_clause, values = cql_where_clause(where) cql << " WHERE #{where_clause}" else where = connection.prepare(cql) end results = connection.find(cql, values, ) results.rows.first["count"] end |
#create(attributes) ⇒ Object
Returns a newly created record. If the record is not valid then it won’t be persisted.
245 246 247 248 249 |
# File 'lib/cassie/model.rb', line 245 def create(attributes) record = new(attributes) record.save record end |
#create!(attributes) ⇒ Object
Returns a newly created record or raises an ActiveRecord::RecordInvalid error if the record is not valid.
253 254 255 256 257 |
# File 'lib/cassie/model.rb', line 253 def create!(attributes) record = new(attributes) record.save! record end |
#delete_all(key_hash) ⇒ Object
Delete all rows from the table that match the key hash. This method bypasses any destroy callbacks defined on the model.
261 262 263 264 265 266 267 |
# File 'lib/cassie/model.rb', line 261 def delete_all(key_hash) cleanup_up_hash = {} key_hash.each do |name, value| cleanup_up_hash[column_name(name)] = value end connection.delete(full_table_name, cleanup_up_hash) end |
#find(where) ⇒ Object
Find a single record that matches the where argument.
203 204 205 206 207 208 209 210 |
# File 'lib/cassie/model.rb', line 203 def find(where) = nil if where.is_a?(Hash) && where.include?(:options) where = where.dup = where.delete(:options) end find_all(where: where, limit: 1, options: ).first end |
#find!(where) ⇒ Object
Find a single record that matches the where argument or raise an ActiveRecord::RecordNotFound error if none is found.
214 215 216 217 218 |
# File 'lib/cassie/model.rb', line 214 def find!(where) record = find(where) raise Cassie::RecordNotFound unless record record end |
#find_all(where:, select: nil, order: nil, limit: nil, options: nil) ⇒ Object
Find all records.
The where argument can be a Hash, Array, or String WHERE clause to filter the rows returned. It is required so that you don’t accidentally release code that returns all rows. If you really want to select all rows from a table you can specify the value :all.
The select argument can be used to limit which columns are returned and should be passed as an array of column names which can include aliases.
The order argument is a CQL fragment indicating the order. Note that Cassandra will only allow ordering by rows in the primary key.
The limit argument specifies how many rows to return.
You can provide a block to this method in which case it will yield each record as it is foundto the block instead of returning them.
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 |
# File 'lib/cassie/model.rb', line 162 def find_all(where:, select: nil, order: nil, limit: nil, options: nil) columns = (select ? Array(select).collect{|c| column_name(c)} : column_names) cql = "SELECT #{columns.join(', ')} FROM #{full_table_name}" values = nil raise ArgumentError.new("Where clause cannot be blank. Pass :all to find all records.") if where.blank? if where && where != :all where_clause, values = cql_where_clause(where) else values = [] end cql << " WHERE #{where_clause}" if where_clause if order cql << " ORDER BY #{order}" end if limit cql << " LIMIT ?" values << Integer(limit) end results = connection.find(cql, values, ) records = [] unless block_given? loop do results.each do |row| record = new(row) record.instance_variable_set(:@persisted, true) if block_given? yield record else records << record end end break if results.last_page? results = results.next_page end records end |
#full_table_name ⇒ Object
Return the full table name including the keyspace.
137 138 139 140 141 142 143 |
# File 'lib/cassie/model.rb', line 137 def full_table_name if _keyspace "#{keyspace}.#{table_name}" else table_name end end |
#keyspace ⇒ Object
Return the keyspace name where the table is located.
132 133 134 |
# File 'lib/cassie/model.rb', line 132 def keyspace connection.config.keyspace(_keyspace) end |
#keyspace=(name) ⇒ Object
Set the keyspace for the table. The name should be an abstract keyspace name that is mapped to an actual keyspace name in the configuration. If the name provided is not mapped in the configuration, then the raw value will be used.
127 128 129 |
# File 'lib/cassie/model.rb', line 127 def keyspace=(name) self._keyspace = name.to_s end |
#offset_to_id(key, offset, order: nil, batch_size: 1000, min: nil, max: nil) ⇒ Object
Since Cassandra doesn’t support offset we need to find the order key of record at the specified the offset.
The key is a Hash describing the primary keys to search minus the last column defined for the primary key. This column is assumed to be an ordering key. If it isn’t, this method will fail.
The order argument can be used to specify an order for the ordering key (:asc or :desc). It will default to the natural order of the last ordering key as defined by the ordering_key method.
The min and max can be used to limit the offset calculation to a range of values (exclusive).
293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 |
# File 'lib/cassie/model.rb', line 293 def offset_to_id(key, offset, order: nil, batch_size: 1000, min: nil, max: nil) ordering_key = primary_key.last cluster_order = _ordering_keys[ordering_key] || :asc order ||= cluster_order order_cql = "#{ordering_key} #{order}" unless order == cluster_order from = (order == :desc ? max : min) to = (order == :desc ? min : max) loop do limit = (offset > batch_size ? batch_size : offset + 1) conditions_cql = [] conditions = [] if from conditions_cql << "#{ordering_key} #{order == :desc ? '<' : '>'} ?" conditions << from end if to conditions_cql << "#{ordering_key} #{order == :desc ? '>' : '<'} ?" conditions << to end key.each do |name, value| conditions_cql << "#{column_name(name)} = ?" conditions << value end conditions.unshift(conditions_cql.join(" AND ")) results = find_all(:select => [ordering_key], :where => conditions, :limit => limit, :order => order_cql) last_row = results.last if results.size == limit last_id = last_row.send(ordering_key) if last_row if last_id.nil? return nil elsif limit >= offset return last_id else offset -= results.size from = last_id end end end |
#ordering_key(name, order) ⇒ Object
Define and ordering key for the table. The order attribute should be either :asc or :desc
118 119 120 121 122 |
# File 'lib/cassie/model.rb', line 118 def ordering_key(name, order) order = order.to_sym raise ArgumentError.new("order must be either :asc or :desc") unless order == :asc || order == :desc _ordering_keys[name.to_sym] = order end |
#primary_key ⇒ Object
Return an array of column names for the table primary key.
113 114 115 |
# File 'lib/cassie/model.rb', line 113 def primary_key _primary_key end |
#primary_key=(value) ⇒ Object
Set the primary key for the table. The value should be set as an array with the clustering key first.
102 103 104 105 106 107 108 109 110 |
# File 'lib/cassie/model.rb', line 102 def primary_key=(value) self._primary_key = Array(value).map { |column| if column.is_a?(Array) column.map(&:to_sym) else column.to_sym end }.flatten end |