cequel 1.0.0.pre.1 → 1.0.0.pre.2
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.
- checksums.yaml +4 -4
- data/lib/cequel.rb +2 -0
- data/lib/cequel/model.rb +2 -0
- data/lib/cequel/model/base.rb +10 -0
- data/lib/cequel/model/collection.rb +5 -1
- data/lib/cequel/model/dirty.rb +62 -0
- data/lib/cequel/model/errors.rb +1 -0
- data/lib/cequel/model/record_set.rb +61 -72
- data/lib/cequel/model/schema.rb +2 -1
- data/lib/cequel/model/scoped.rb +1 -1
- data/lib/cequel/model/secondary_indexes.rb +31 -0
- data/lib/cequel/model/validations.rb +1 -1
- data/lib/cequel/schema/column.rb +18 -2
- data/lib/cequel/schema/table.rb +6 -6
- data/lib/cequel/schema/table_synchronizer.rb +3 -3
- data/lib/cequel/schema/table_writer.rb +2 -1
- data/lib/cequel/util.rb +46 -0
- data/lib/cequel/version.rb +1 -1
- data/spec/examples/model/dirty_spec.rb +68 -0
- data/spec/examples/model/record_set_spec.rb +33 -2
- data/spec/examples/model/schema_spec.rb +1 -1
- data/spec/examples/model/secondary_index_spec.rb +45 -0
- data/spec/examples/model/spec_helper.rb +0 -1
- data/spec/examples/schema/table_reader_spec.rb +8 -8
- data/spec/examples/schema/table_writer_spec.rb +8 -8
- metadata +14 -6
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 7888f93ffd3d74bdfef143a9c8d18c6c9f2f4ba1
         | 
| 4 | 
            +
              data.tar.gz: 831e5a90a03cf1c22ddf08421284107254aa59a6
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 41a8585f9c78171c34944551914e4e06b44fabe615b9192901782b6653be345314c63ad4e4b5b048818bb10e1d4085aad24006285a9bd573489153b24719ccc3
         | 
| 7 | 
            +
              data.tar.gz: 90297a4b794c2eb265ffdc7659f80c1b90ef8870c1d04ff910d4d015e425a47395b8151fa72c8cf85266538e5e7fe3c495b9433751776eb727ee5983f986314c
         | 
    
        data/lib/cequel.rb
    CHANGED
    
    
    
        data/lib/cequel/model.rb
    CHANGED
    
    | @@ -8,6 +8,7 @@ require 'cequel/model/collection' | |
| 8 8 | 
             
            require 'cequel/model/persistence'
         | 
| 9 9 | 
             
            require 'cequel/model/record_set'
         | 
| 10 10 | 
             
            require 'cequel/model/scoped'
         | 
| 11 | 
            +
            require 'cequel/model/secondary_indexes'
         | 
| 11 12 | 
             
            require 'cequel/model/associations'
         | 
| 12 13 | 
             
            require 'cequel/model/association_collection'
         | 
| 13 14 | 
             
            require 'cequel/model/belongs_to_association'
         | 
| @@ -15,6 +16,7 @@ require 'cequel/model/has_many_association' | |
| 15 16 | 
             
            require 'cequel/model/mass_assignment'
         | 
| 16 17 | 
             
            require 'cequel/model/callbacks'
         | 
| 17 18 | 
             
            require 'cequel/model/validations'
         | 
| 19 | 
            +
            require 'cequel/model/dirty'
         | 
| 18 20 |  | 
| 19 21 | 
             
            require 'cequel/model/base'
         | 
| 20 22 |  | 
    
        data/lib/cequel/model/base.rb
    CHANGED
    
    | @@ -9,9 +9,11 @@ module Cequel | |
| 9 9 | 
             
                  include Cequel::Model::Persistence
         | 
| 10 10 | 
             
                  include Cequel::Model::Associations
         | 
| 11 11 | 
             
                  extend Cequel::Model::Scoped
         | 
| 12 | 
            +
                  extend Cequel::Model::SecondaryIndexes
         | 
| 12 13 | 
             
                  include Cequel::Model::MassAssignment
         | 
| 13 14 | 
             
                  include Cequel::Model::Callbacks
         | 
| 14 15 | 
             
                  include Cequel::Model::Validations
         | 
| 16 | 
            +
                  include Cequel::Model::Dirty
         | 
| 15 17 | 
             
                  extend ActiveModel::Naming
         | 
| 16 18 | 
             
                  include ActiveModel::Serializers::JSON
         | 
| 17 19 | 
             
                  include ActiveModel::Serializers::Xml
         | 
| @@ -41,6 +43,14 @@ module Cequel | |
| 41 43 | 
             
                    instance_eval(&block) if block
         | 
| 42 44 | 
             
                  end
         | 
| 43 45 |  | 
| 46 | 
            +
                  def ==(other)
         | 
| 47 | 
            +
                    if key_values.any? { |value| value.nil? }
         | 
| 48 | 
            +
                      super
         | 
| 49 | 
            +
                    else
         | 
| 50 | 
            +
                      self.class == other.class && key_values == other.key_values
         | 
| 51 | 
            +
                    end
         | 
| 52 | 
            +
                  end
         | 
| 53 | 
            +
             | 
| 44 54 | 
             
                  def inspect
         | 
| 45 55 | 
             
                    inspected_attributes = attributes.each_pair.map do |attr, value|
         | 
| 46 56 | 
             
                      inspected_value = value.is_a?(CassandraCQL::UUID) ?
         | 
| @@ -10,6 +10,7 @@ module Cequel | |
| 10 10 | 
             
                  extend Forwardable
         | 
| 11 11 |  | 
| 12 12 | 
             
                  def_delegators :@model, :loaded?, :updater, :deleter
         | 
| 13 | 
            +
                  def_delegators :__getobj__, :clone, :dup
         | 
| 13 14 |  | 
| 14 15 | 
             
                  attr_reader :column_name
         | 
| 15 16 |  | 
| @@ -50,7 +51,9 @@ module Cequel | |
| 50 51 | 
             
                  private
         | 
| 51 52 |  | 
| 52 53 | 
             
                  def to_modify(&block)
         | 
| 53 | 
            -
                    if loaded? | 
| 54 | 
            +
                    if loaded?
         | 
| 55 | 
            +
                      @model.__send__("#{@column_name}_will_change!")
         | 
| 56 | 
            +
                      block.()
         | 
| 54 57 | 
             
                    else modifications << block
         | 
| 55 58 | 
             
                    end
         | 
| 56 59 | 
             
                    self
         | 
| @@ -175,6 +178,7 @@ module Cequel | |
| 175 178 | 
             
                    updater.set_add(column_name, object)
         | 
| 176 179 | 
             
                    to_modify { super }
         | 
| 177 180 | 
             
                  end
         | 
| 181 | 
            +
                  alias_method :<<, :add
         | 
| 178 182 |  | 
| 179 183 | 
             
                  def clear
         | 
| 180 184 | 
             
                    deleter.delete_columns(column_name)
         | 
| @@ -0,0 +1,62 @@ | |
| 1 | 
            +
            module Cequel
         | 
| 2 | 
            +
             | 
| 3 | 
            +
              module Model
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                module Dirty
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                  extend ActiveSupport::Concern
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                  included { include ActiveModel::Dirty }
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                  module ClassMethods
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                    def key(name, *)
         | 
| 14 | 
            +
                      define_attribute_method(name)
         | 
| 15 | 
            +
                      super
         | 
| 16 | 
            +
                    end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                    def column(name, *)
         | 
| 19 | 
            +
                      define_attribute_method(name)
         | 
| 20 | 
            +
                      super
         | 
| 21 | 
            +
                    end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                    def set(name, *)
         | 
| 24 | 
            +
                      define_attribute_method(name)
         | 
| 25 | 
            +
                      super
         | 
| 26 | 
            +
                    end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                    def list(name, *)
         | 
| 29 | 
            +
                      define_attribute_method(name)
         | 
| 30 | 
            +
                      super
         | 
| 31 | 
            +
                    end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                    def map(name, *)
         | 
| 34 | 
            +
                      define_attribute_method(name)
         | 
| 35 | 
            +
                      super
         | 
| 36 | 
            +
                    end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                  end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                  def save(options = {})
         | 
| 41 | 
            +
                    super.tap do |success|
         | 
| 42 | 
            +
                      if success
         | 
| 43 | 
            +
                        @previously_changed = changes
         | 
| 44 | 
            +
                        @changed_attributes.clear
         | 
| 45 | 
            +
                      end
         | 
| 46 | 
            +
                    end
         | 
| 47 | 
            +
                  end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                  private
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                  def write_attribute(name, value)
         | 
| 52 | 
            +
                    if loaded? && value != read_attribute(name)
         | 
| 53 | 
            +
                      __send__("#{name}_will_change!")
         | 
| 54 | 
            +
                    end
         | 
| 55 | 
            +
                    super
         | 
| 56 | 
            +
                  end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
              end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
            end
         | 
    
        data/lib/cequel/model/errors.rb
    CHANGED
    
    
| @@ -5,14 +5,26 @@ module Cequel | |
| 5 5 | 
             
                class RecordSet
         | 
| 6 6 |  | 
| 7 7 | 
             
                  extend Forwardable
         | 
| 8 | 
            +
                  extend Cequel::Util::HashAccessors
         | 
| 8 9 | 
             
                  include Enumerable
         | 
| 9 10 |  | 
| 10 11 | 
             
                  Bound = Struct.new(:value, :inclusive)
         | 
| 11 12 |  | 
| 12 | 
            -
                  def  | 
| 13 | 
            -
                     | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 13 | 
            +
                  def self.default_attributes
         | 
| 14 | 
            +
                    {:scoped_key_values => [], :select_columns => []}
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                  def self.create(clazz, attributes = {})
         | 
| 18 | 
            +
                    attributes = default_attributes.merge!(attributes)
         | 
| 19 | 
            +
                    if attributes[:scoped_key_values].length >= clazz.partition_key_columns.length
         | 
| 20 | 
            +
                      SinglePartitionRecordSet.new(clazz, attributes)
         | 
| 21 | 
            +
                    else
         | 
| 22 | 
            +
                      RecordSet.new(clazz, attributes)
         | 
| 23 | 
            +
                    end
         | 
| 24 | 
            +
                  end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  def initialize(clazz, attributes)
         | 
| 27 | 
            +
                    @clazz, @attributes = clazz, attributes
         | 
| 16 28 | 
             
                  end
         | 
| 17 29 |  | 
| 18 30 | 
             
                  def all
         | 
| @@ -21,18 +33,29 @@ module Cequel | |
| 21 33 |  | 
| 22 34 | 
             
                  def select(*columns)
         | 
| 23 35 | 
             
                    return super if block_given?
         | 
| 24 | 
            -
                    scoped { | | 
| 36 | 
            +
                    scoped { |attributes| attributes[:select_columns].concat(columns) }
         | 
| 25 37 | 
             
                  end
         | 
| 26 38 |  | 
| 27 39 | 
             
                  def limit(count)
         | 
| 28 | 
            -
                    scoped | 
| 40 | 
            +
                    scoped(:row_limit => count)
         | 
| 41 | 
            +
                  end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                  def where(column_name, value)
         | 
| 44 | 
            +
                    column = clazz.table_schema.column(column_name)
         | 
| 45 | 
            +
                    raise IllegalQuery,
         | 
| 46 | 
            +
                      "Can't scope by more than one indexed column in the same query" if scoped_indexed_column
         | 
| 47 | 
            +
                    raise ArgumentError,
         | 
| 48 | 
            +
                      "No column #{column_name} configured for #{clazz.name}" unless column
         | 
| 49 | 
            +
                    raise ArgumentError,
         | 
| 50 | 
            +
                      "Use the `at` method to restrict scope by primary key" unless column.data_column?
         | 
| 51 | 
            +
                    raise ArgumentError,
         | 
| 52 | 
            +
                      "Can't scope by non-indexed column #{column_name}" unless column.indexed?
         | 
| 53 | 
            +
                    scoped(scoped_indexed_column: {column_name => value})
         | 
| 29 54 | 
             
                  end
         | 
| 30 55 |  | 
| 31 56 | 
             
                  def at(*scoped_key_values)
         | 
| 32 | 
            -
                     | 
| 33 | 
            -
                       | 
| 34 | 
            -
                    scoped(record_set_class) do |record_set|
         | 
| 35 | 
            -
                      record_set.scoped_key_values.concat(scoped_key_values)
         | 
| 57 | 
            +
                    scoped do |attributes|
         | 
| 58 | 
            +
                      attributes[:scoped_key_values].concat(scoped_key_values)
         | 
| 36 59 | 
             
                    end
         | 
| 37 60 | 
             
                  end
         | 
| 38 61 |  | 
| @@ -58,22 +81,18 @@ module Cequel | |
| 58 81 | 
             
                  end
         | 
| 59 82 |  | 
| 60 83 | 
             
                  def after(start_key)
         | 
| 61 | 
            -
                    scoped  | 
| 62 | 
            -
                      record_set.lower_bound = Bound.new(start_key, false)
         | 
| 63 | 
            -
                    end
         | 
| 84 | 
            +
                    scoped(lower_bound: Bound.new(start_key, false))
         | 
| 64 85 | 
             
                  end
         | 
| 65 86 |  | 
| 66 87 | 
             
                  def before(end_key)
         | 
| 67 | 
            -
                    scoped  | 
| 68 | 
            -
                      record_set.upper_bound = Bound.new(end_key, false)
         | 
| 69 | 
            -
                    end
         | 
| 88 | 
            +
                    scoped(upper_bound: Bound.new(end_key, false))
         | 
| 70 89 | 
             
                  end
         | 
| 71 90 |  | 
| 72 91 | 
             
                  def in(range)
         | 
| 73 | 
            -
                    scoped | 
| 74 | 
            -
                       | 
| 75 | 
            -
                       | 
| 76 | 
            -
                     | 
| 92 | 
            +
                    scoped(
         | 
| 93 | 
            +
                      lower_bound: Bound.new(range.first, true),
         | 
| 94 | 
            +
                      upper_bound: Bound.new(range.last, !range.exclude_end?)
         | 
| 95 | 
            +
                    )
         | 
| 77 96 | 
             
                  end
         | 
| 78 97 |  | 
| 79 98 | 
             
                  def first(count = nil)
         | 
| @@ -116,29 +135,17 @@ module Cequel | |
| 116 135 | 
             
                    end
         | 
| 117 136 | 
             
                  end
         | 
| 118 137 |  | 
| 119 | 
            -
                  protected
         | 
| 120 | 
            -
                  attr_accessor :row_limit
         | 
| 121 | 
            -
                  attr_reader :select_columns, :scoped_key_values,
         | 
| 122 | 
            -
                    :lower_bound, :upper_bound
         | 
| 123 | 
            -
             | 
| 124 | 
            -
                  def reversed?
         | 
| 125 | 
            -
                    false
         | 
| 126 | 
            -
                  end
         | 
| 127 | 
            -
             | 
| 128 | 
            -
                  def lower_bound=(bound)
         | 
| 129 | 
            -
                    @lower_bound = bound
         | 
| 130 | 
            -
                  end
         | 
| 131 | 
            -
             | 
| 132 | 
            -
                  def upper_bound=(bound)
         | 
| 133 | 
            -
                    @upper_bound = bound
         | 
| 134 | 
            -
                  end
         | 
| 135 | 
            -
             | 
| 136 138 | 
             
                  def data_set
         | 
| 137 139 | 
             
                    @data_set ||= construct_data_set
         | 
| 138 140 | 
             
                  end
         | 
| 139 141 |  | 
| 142 | 
            +
                  protected
         | 
| 143 | 
            +
                  attr_reader :attributes
         | 
| 144 | 
            +
                  hattr_reader :attributes, :select_columns, :scoped_key_values, :row_limit,
         | 
| 145 | 
            +
                    :lower_bound, :upper_bound, :scoped_indexed_column
         | 
| 146 | 
            +
             | 
| 140 147 | 
             
                  def next_batch_from(row)
         | 
| 141 | 
            -
                     | 
| 148 | 
            +
                    after(row[range_key_name])
         | 
| 142 149 | 
             
                  end
         | 
| 143 150 |  | 
| 144 151 | 
             
                  def find_nested_batches_from(row, options, &block)
         | 
| @@ -176,23 +183,10 @@ module Cequel | |
| 176 183 | 
             
                    scoped_key_columns.map { |column| column.name }
         | 
| 177 184 | 
             
                  end
         | 
| 178 185 |  | 
| 179 | 
            -
                  def chain_from(collection)
         | 
| 180 | 
            -
                    @select_columns = collection.select_columns.dup
         | 
| 181 | 
            -
                    @scoped_key_values = collection.scoped_key_values.dup
         | 
| 182 | 
            -
                    @lower_bound = collection.lower_bound
         | 
| 183 | 
            -
                    @upper_bound = collection.upper_bound
         | 
| 184 | 
            -
                    @row_limit = collection.row_limit
         | 
| 185 | 
            -
                    self
         | 
| 186 | 
            -
                  end
         | 
| 187 | 
            -
             | 
| 188 186 | 
             
                  private
         | 
| 189 187 | 
             
                  attr_reader :clazz
         | 
| 190 188 | 
             
                  def_delegators :clazz, :connection
         | 
| 191 189 |  | 
| 192 | 
            -
                  def scoped(record_set_class = self.class, &block)
         | 
| 193 | 
            -
                    record_set_class.new(clazz).chain_from(self).tap(&block)
         | 
| 194 | 
            -
                  end
         | 
| 195 | 
            -
             | 
| 196 190 | 
             
                  def next_key_column
         | 
| 197 191 | 
             
                    clazz.key_columns[scoped_key_values.length + 1]
         | 
| 198 192 | 
             
                  end
         | 
| @@ -217,6 +211,7 @@ module Cequel | |
| 217 211 | 
             
                      fragment = construct_bound_fragment(upper_bound, '<')
         | 
| 218 212 | 
             
                      data_set = data_set.where(fragment, upper_bound.value)
         | 
| 219 213 | 
             
                    end
         | 
| 214 | 
            +
                    data_set = data_set.where(scoped_indexed_column) if scoped_indexed_column
         | 
| 220 215 | 
             
                    data_set
         | 
| 221 216 | 
             
                  end
         | 
| 222 217 |  | 
| @@ -225,43 +220,41 @@ module Cequel | |
| 225 220 | 
             
                    "TOKEN(#{range_key_name}) #{operator} TOKEN(?)"
         | 
| 226 221 | 
             
                  end
         | 
| 227 222 |  | 
| 223 | 
            +
                  def scoped(new_attributes = {}, &block)
         | 
| 224 | 
            +
                    attributes_copy = Marshal.load(Marshal.dump(attributes))
         | 
| 225 | 
            +
                    attributes_copy.merge!(new_attributes)
         | 
| 226 | 
            +
                    attributes_copy.tap(&block) if block
         | 
| 227 | 
            +
                    RecordSet.create(clazz, attributes_copy)
         | 
| 228 | 
            +
                  end
         | 
| 229 | 
            +
             | 
| 228 230 | 
             
                end
         | 
| 229 231 |  | 
| 230 | 
            -
                class  | 
| 232 | 
            +
                class SinglePartitionRecordSet < RecordSet
         | 
| 231 233 |  | 
| 232 | 
            -
                   | 
| 233 | 
            -
                    super
         | 
| 234 | 
            -
                    @reversed = false
         | 
| 235 | 
            -
                  end
         | 
| 234 | 
            +
                  hattr_inquirer :attributes, :reversed
         | 
| 236 235 |  | 
| 237 236 | 
             
                  def from(start_key)
         | 
| 238 | 
            -
                    scoped  | 
| 239 | 
            -
                      record_set.lower_bound = Bound.new(start_key, true)
         | 
| 240 | 
            -
                    end
         | 
| 237 | 
            +
                    scoped(lower_bound: Bound.new(start_key, true))
         | 
| 241 238 | 
             
                  end
         | 
| 242 239 |  | 
| 243 240 | 
             
                  def upto(end_key)
         | 
| 244 | 
            -
                    scoped  | 
| 245 | 
            -
                      record_set.upper_bound = Bound.new(end_key, true)
         | 
| 246 | 
            -
                    end
         | 
| 241 | 
            +
                    scoped(upper_bound: Bound.new(end_key, true))
         | 
| 247 242 | 
             
                  end
         | 
| 248 243 |  | 
| 249 244 | 
             
                  def reverse
         | 
| 250 | 
            -
                    scoped | 
| 245 | 
            +
                    scoped(reversed: !reversed?)
         | 
| 251 246 | 
             
                  end
         | 
| 252 247 |  | 
| 253 248 | 
             
                  def last
         | 
| 254 249 | 
             
                    reverse.first
         | 
| 255 250 | 
             
                  end
         | 
| 256 251 |  | 
| 257 | 
            -
                   | 
| 258 | 
            -
             | 
| 259 | 
            -
                     | 
| 260 | 
            -
                    self
         | 
| 252 | 
            +
                  # @api private
         | 
| 253 | 
            +
                  def next_batch_from(row)
         | 
| 254 | 
            +
                    reversed? ? before(row[range_key_name]) : super
         | 
| 261 255 | 
             
                  end
         | 
| 262 256 |  | 
| 263 257 | 
             
                  protected
         | 
| 264 | 
            -
                  attr_writer :reversed
         | 
| 265 258 |  | 
| 266 259 | 
             
                  def construct_data_set
         | 
| 267 260 | 
             
                    data_set = super
         | 
| @@ -269,10 +262,6 @@ module Cequel | |
| 269 262 | 
             
                    data_set
         | 
| 270 263 | 
             
                  end
         | 
| 271 264 |  | 
| 272 | 
            -
                  def reversed?
         | 
| 273 | 
            -
                    @reversed
         | 
| 274 | 
            -
                  end
         | 
| 275 | 
            -
             | 
| 276 265 | 
             
                  def construct_bound_fragment(bound, base_operator)
         | 
| 277 266 | 
             
                    operator = bound.inclusive ? "#{base_operator}=" : base_operator
         | 
| 278 267 | 
             
                    "#{range_key_name} #{operator} ?"
         | 
    
        data/lib/cequel/model/schema.rb
    CHANGED
    
    | @@ -9,7 +9,8 @@ module Cequel | |
| 9 9 | 
             
                  module ClassMethods
         | 
| 10 10 | 
             
                    extend Forwardable
         | 
| 11 11 |  | 
| 12 | 
            -
                    def_delegators :table_schema, :key_columns, :key_column_names
         | 
| 12 | 
            +
                    def_delegators :table_schema, :key_columns, :key_column_names,
         | 
| 13 | 
            +
                      :partition_key_columns, :clustering_columns
         | 
| 13 14 |  | 
| 14 15 | 
             
                    def synchronize_schema
         | 
| 15 16 | 
             
                      Cequel::Schema::TableSynchronizer.
         | 
    
        data/lib/cequel/model/scoped.rb
    CHANGED
    
    
| @@ -0,0 +1,31 @@ | |
| 1 | 
            +
            module Cequel
         | 
| 2 | 
            +
             | 
| 3 | 
            +
              module Model
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                module SecondaryIndexes
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                  def column(name, type, options = {})
         | 
| 8 | 
            +
                    super
         | 
| 9 | 
            +
                    name = name.to_sym
         | 
| 10 | 
            +
                    if options[:index]
         | 
| 11 | 
            +
                      instance_eval <<-RUBY, __FILE__, __LINE__+1
         | 
| 12 | 
            +
                        def with_#{name}(value)
         | 
| 13 | 
            +
                          all.where(#{name.inspect}, value)
         | 
| 14 | 
            +
                        end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                        def find_by_#{name}(value)
         | 
| 17 | 
            +
                          with_#{name}(value).first
         | 
| 18 | 
            +
                        end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                        def find_all_by_#{name}(value)
         | 
| 21 | 
            +
                          with_#{name}(value).to_a
         | 
| 22 | 
            +
                        end
         | 
| 23 | 
            +
                      RUBY
         | 
| 24 | 
            +
                    end
         | 
| 25 | 
            +
                  end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
              end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
            end
         | 
    
        data/lib/cequel/schema/column.rb
    CHANGED
    
    | @@ -10,6 +10,22 @@ module Cequel | |
| 10 10 | 
             
                    @name, @type = name, type
         | 
| 11 11 | 
             
                  end
         | 
| 12 12 |  | 
| 13 | 
            +
                  def key?
         | 
| 14 | 
            +
                    partition_key? || clustering_column?
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                  def partition_key?
         | 
| 18 | 
            +
                    false
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                  def clustering_column?
         | 
| 22 | 
            +
                    false
         | 
| 23 | 
            +
                  end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                  def data_column?
         | 
| 26 | 
            +
                    !key?
         | 
| 27 | 
            +
                  end
         | 
| 28 | 
            +
             | 
| 13 29 | 
             
                  def to_cql
         | 
| 14 30 | 
             
                    "#{@name} #{@type}"
         | 
| 15 31 | 
             
                  end
         | 
| @@ -53,8 +69,8 @@ module Cequel | |
| 53 69 | 
             
                    "#{@name} #{@clustering_order}"
         | 
| 54 70 | 
             
                  end
         | 
| 55 71 |  | 
| 56 | 
            -
                  def  | 
| 57 | 
            -
                     | 
| 72 | 
            +
                  def clustering_column?
         | 
| 73 | 
            +
                    true
         | 
| 58 74 | 
             
                  end
         | 
| 59 75 |  | 
| 60 76 | 
             
                end
         | 
    
        data/lib/cequel/schema/table.rb
    CHANGED
    
    | @@ -8,7 +8,7 @@ module Cequel | |
| 8 8 |  | 
| 9 9 | 
             
                  attr_reader :name,
         | 
| 10 10 | 
             
                              :columns,
         | 
| 11 | 
            -
                              : | 
| 11 | 
            +
                              :partition_key_columns,
         | 
| 12 12 | 
             
                              :clustering_columns,
         | 
| 13 13 | 
             
                              :data_columns,
         | 
| 14 14 | 
             
                              :properties
         | 
| @@ -16,13 +16,13 @@ module Cequel | |
| 16 16 |  | 
| 17 17 | 
             
                  def initialize(name)
         | 
| 18 18 | 
             
                    @name = name
         | 
| 19 | 
            -
                    @ | 
| 19 | 
            +
                    @partition_key_columns, @clustering_columns, @data_columns = [], [], []
         | 
| 20 20 | 
             
                    @columns, @columns_by_name = [], {}
         | 
| 21 21 | 
             
                    @properties = ActiveSupport::HashWithIndifferentAccess.new
         | 
| 22 22 | 
             
                  end
         | 
| 23 23 |  | 
| 24 24 | 
             
                  def add_key(name, type, clustering_order = nil)
         | 
| 25 | 
            -
                    if @ | 
| 25 | 
            +
                    if @partition_key_columns.empty?
         | 
| 26 26 | 
             
                      unless clustering_order.nil?
         | 
| 27 27 | 
             
                        raise ArgumentError,
         | 
| 28 28 | 
             
                          "Can't set clustering order for partition key #{name}"
         | 
| @@ -35,7 +35,7 @@ module Cequel | |
| 35 35 |  | 
| 36 36 | 
             
                  def add_partition_key(name, type)
         | 
| 37 37 | 
             
                    column = PartitionKey.new(name, type(type))
         | 
| 38 | 
            -
                    @ | 
| 38 | 
            +
                    @partition_key_columns << add_column(column)
         | 
| 39 39 | 
             
                  end
         | 
| 40 40 |  | 
| 41 41 | 
             
                  def add_clustering_column(name, type, clustering_order = nil)
         | 
| @@ -71,7 +71,7 @@ module Cequel | |
| 71 71 | 
             
                  end
         | 
| 72 72 |  | 
| 73 73 | 
             
                  def key_columns
         | 
| 74 | 
            -
                    @ | 
| 74 | 
            +
                    @partition_key_columns + @clustering_columns
         | 
| 75 75 | 
             
                  end
         | 
| 76 76 |  | 
| 77 77 | 
             
                  def key_column_names
         | 
| @@ -79,7 +79,7 @@ module Cequel | |
| 79 79 | 
             
                  end
         | 
| 80 80 |  | 
| 81 81 | 
             
                  def partition_key(name)
         | 
| 82 | 
            -
                    @ | 
| 82 | 
            +
                    @partition_key_columns.find { |column| column.name == name }
         | 
| 83 83 | 
             
                  end
         | 
| 84 84 |  | 
| 85 85 | 
             
                  def clustering_column(name)
         | 
| @@ -86,15 +86,15 @@ module Cequel | |
| 86 86 | 
             
                  end
         | 
| 87 87 |  | 
| 88 88 | 
             
                  def each_key_pair(&block)
         | 
| 89 | 
            -
                    if existing. | 
| 89 | 
            +
                    if existing.partition_key_columns.length != updated.partition_key_columns.length
         | 
| 90 90 | 
             
                      raise InvalidSchemaMigration,
         | 
| 91 | 
            -
                        "Existing partition keys #{existing. | 
| 91 | 
            +
                        "Existing partition keys #{existing.partition_key_columns.map { |key| key.name }.join(',')} differ from specified partition keys #{updated.partition_key_columns.map { |key| key.name }.join(',')}"
         | 
| 92 92 | 
             
                    end
         | 
| 93 93 | 
             
                    if existing.clustering_columns.length != updated.clustering_columns.length
         | 
| 94 94 | 
             
                      raise InvalidSchemaMigration,
         | 
| 95 95 | 
             
                        "Existing clustering keys #{existing.clustering_columns.map { |key| key.name }.join(',')} differ from specified clustering keys #{updated.clustering_columns.map { |key| key.name }.join(',')}"
         | 
| 96 96 | 
             
                    end
         | 
| 97 | 
            -
                    existing. | 
| 97 | 
            +
                    existing.partition_key_columns.zip(updated.partition_key_columns, &block)
         | 
| 98 98 | 
             
                    existing.clustering_columns.zip(updated.clustering_columns, &block)
         | 
| 99 99 | 
             
                  end
         | 
| 100 100 |  | 
| @@ -51,7 +51,8 @@ module Cequel | |
| 51 51 | 
             
                  end
         | 
| 52 52 |  | 
| 53 53 | 
             
                  def keys_cql
         | 
| 54 | 
            -
                    partition_cql = table. | 
| 54 | 
            +
                    partition_cql = table.partition_key_columns.
         | 
| 55 | 
            +
                      map { |key| key.name }.join(', ')
         | 
| 55 56 | 
             
                    if table.clustering_columns.any?
         | 
| 56 57 | 
             
                      nonpartition_cql =
         | 
| 57 58 | 
             
                        table.clustering_columns.map { |key| key.name }.join(', ')
         | 
    
        data/lib/cequel/util.rb
    ADDED
    
    | @@ -0,0 +1,46 @@ | |
| 1 | 
            +
            module Cequel
         | 
| 2 | 
            +
             | 
| 3 | 
            +
              module Util
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                module HashAccessors
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                  def hattr_reader(hash, *attributes)
         | 
| 8 | 
            +
                    attributes.each do |attribute|
         | 
| 9 | 
            +
                      module_eval <<-RUBY, __FILE__, __LINE__+1
         | 
| 10 | 
            +
                        def #{attribute}
         | 
| 11 | 
            +
                          #{hash}[#{attribute.to_sym.inspect}]
         | 
| 12 | 
            +
                        end
         | 
| 13 | 
            +
                      RUBY
         | 
| 14 | 
            +
                    end
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                  def hattr_inquirer(hash, *attributes)
         | 
| 18 | 
            +
                    attributes.each do |attribute|
         | 
| 19 | 
            +
                      module_eval <<-RUBY, __FILE__, __LINE__+1
         | 
| 20 | 
            +
                        def #{attribute}?
         | 
| 21 | 
            +
                          !!#{hash}[#{attribute.to_sym.inspect}]
         | 
| 22 | 
            +
                        end
         | 
| 23 | 
            +
                      RUBY
         | 
| 24 | 
            +
                    end
         | 
| 25 | 
            +
                  end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                  def hattr_writer(hash, *attributes)
         | 
| 28 | 
            +
                    attributes.each do |attribute|
         | 
| 29 | 
            +
                      module_eval <<-RUBY, __FILE__, __LINE__+1
         | 
| 30 | 
            +
                        def #{attribute}=(value)
         | 
| 31 | 
            +
                          #{hash}[#{attribute.to_sym.inspect}] = value
         | 
| 32 | 
            +
                        end
         | 
| 33 | 
            +
                      RUBY
         | 
| 34 | 
            +
                    end
         | 
| 35 | 
            +
                  end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                  def hattr_accessor(hash, *attributes)
         | 
| 38 | 
            +
                    hattr_reader(hash, *attributes)
         | 
| 39 | 
            +
                    hattr_writer(hash, *attributes)
         | 
| 40 | 
            +
                  end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
              end
         | 
| 45 | 
            +
              
         | 
| 46 | 
            +
            end
         | 
    
        data/lib/cequel/version.rb
    CHANGED
    
    
| @@ -0,0 +1,68 @@ | |
| 1 | 
            +
            require File.expand_path('../spec_helper', __FILE__)
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Cequel::Model::Dirty do
         | 
| 4 | 
            +
              model :Post do
         | 
| 5 | 
            +
                key :permalink, :text
         | 
| 6 | 
            +
                column :title, :text
         | 
| 7 | 
            +
                set :categories, :text
         | 
| 8 | 
            +
              end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              context 'loaded model' do
         | 
| 11 | 
            +
                let(:post) do
         | 
| 12 | 
            +
                  Post.create!(
         | 
| 13 | 
            +
                    permalink: 'cequel',
         | 
| 14 | 
            +
                    title: 'Cequel',
         | 
| 15 | 
            +
                    categories: Set['Libraries']
         | 
| 16 | 
            +
                  )
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                it 'should not have changed attributes by default' do
         | 
| 20 | 
            +
                  post.changed_attributes.should be_empty
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                it 'should have changed attributes if attributes change' do
         | 
| 24 | 
            +
                  post.title = 'Cequel ORM'
         | 
| 25 | 
            +
                  post.changed_attributes.
         | 
| 26 | 
            +
                    should == {:title => 'Cequel'}.with_indifferent_access
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                it 'should not have changed attributes if attribute set to the same thing' do
         | 
| 30 | 
            +
                  post.title = 'Cequel'
         | 
| 31 | 
            +
                  post.changed_attributes.should be_empty
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                it 'should support *_changed? method' do
         | 
| 35 | 
            +
                  post.title = 'Cequel ORM'
         | 
| 36 | 
            +
                  post.title_changed?.should be_true
         | 
| 37 | 
            +
                end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                it 'should not have changed attributes after save' do
         | 
| 40 | 
            +
                  post.title = 'Cequel ORM'
         | 
| 41 | 
            +
                  post.save
         | 
| 42 | 
            +
                  post.changed_attributes.should be_empty
         | 
| 43 | 
            +
                end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                it 'should have previous changes after save' do
         | 
| 46 | 
            +
                  post.title = 'Cequel ORM'
         | 
| 47 | 
            +
                  post.save
         | 
| 48 | 
            +
                  post.previous_changes.
         | 
| 49 | 
            +
                    should == { :title => ['Cequel', 'Cequel ORM'] }.with_indifferent_access
         | 
| 50 | 
            +
                end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                it 'should detect changes to collections' do
         | 
| 53 | 
            +
                  post.categories << 'Gems'
         | 
| 54 | 
            +
                  post.changes.should ==
         | 
| 55 | 
            +
                    {categories: [Set['Libraries'], Set['Libraries', 'Gems']]}.
         | 
| 56 | 
            +
                    with_indifferent_access
         | 
| 57 | 
            +
                end
         | 
| 58 | 
            +
              end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
              context 'unloaded model' do
         | 
| 61 | 
            +
                let(:post) { Post['cequel'] }
         | 
| 62 | 
            +
             | 
| 63 | 
            +
                it 'should not track changes' do
         | 
| 64 | 
            +
                  post.title = 'Cequel'
         | 
| 65 | 
            +
                  post.changes.should be_empty
         | 
| 66 | 
            +
                end
         | 
| 67 | 
            +
              end
         | 
| 68 | 
            +
            end
         | 
| @@ -12,13 +12,15 @@ describe Cequel::Model::RecordSet do | |
| 12 12 | 
             
                key :permalink, :text
         | 
| 13 13 | 
             
                column :title, :text
         | 
| 14 14 | 
             
                column :body, :text
         | 
| 15 | 
            -
                column :author_id, :uuid
         | 
| 15 | 
            +
                column :author_id, :uuid, :index => true
         | 
| 16 | 
            +
                column :author_name, :text, :index => true
         | 
| 16 17 | 
             
                list :tags, :text
         | 
| 17 18 | 
             
                set :categories, :text
         | 
| 18 19 | 
             
                map :shares, :text, :int
         | 
| 19 20 | 
             
              end
         | 
| 20 21 |  | 
| 21 22 | 
             
              let(:subdomains) { [] }
         | 
| 23 | 
            +
              let(:uuids) { Array.new(2) { CassandraCQL::UUID.new }}
         | 
| 22 24 |  | 
| 23 25 | 
             
              before do
         | 
| 24 26 | 
             
                cequel.batch do
         | 
| @@ -36,7 +38,8 @@ describe Cequel::Model::RecordSet do | |
| 36 38 | 
             
                      :blog_subdomain => 'cassandra',
         | 
| 37 39 | 
             
                      :permalink => "cequel#{i}",
         | 
| 38 40 | 
             
                      :title => "Cequel #{i}",
         | 
| 39 | 
            -
                      :body => "Post number #{i}"
         | 
| 41 | 
            +
                      :body => "Post number #{i}",
         | 
| 42 | 
            +
                      :author_id => uuids[i%2]
         | 
| 40 43 | 
             
                    )
         | 
| 41 44 | 
             
                    cequel[:posts].insert(
         | 
| 42 45 | 
             
                      :blog_subdomain => 'postgres',
         | 
| @@ -276,6 +279,34 @@ describe Cequel::Model::RecordSet do | |
| 276 279 | 
             
                end
         | 
| 277 280 | 
             
              end
         | 
| 278 281 |  | 
| 282 | 
            +
              describe '#where' do
         | 
| 283 | 
            +
                it 'should correctly query for secondary indexed columns' do
         | 
| 284 | 
            +
                  Post.where(:author_id, uuids.first).map(&:permalink).
         | 
| 285 | 
            +
                    should == %w(cequel0 cequel2 cequel4)
         | 
| 286 | 
            +
                end
         | 
| 287 | 
            +
             | 
| 288 | 
            +
                it 'should raise ArgumentError if column is not recognized' do
         | 
| 289 | 
            +
                  expect { Post.where(:bogus, 'Business') }.
         | 
| 290 | 
            +
                    to raise_error(ArgumentError)
         | 
| 291 | 
            +
                end
         | 
| 292 | 
            +
             | 
| 293 | 
            +
                it 'should raise ArgumentError if column is not indexed' do
         | 
| 294 | 
            +
                  expect { Post.where(:title, 'Cequel 0') }.
         | 
| 295 | 
            +
                    to raise_error(ArgumentError)
         | 
| 296 | 
            +
                end
         | 
| 297 | 
            +
             | 
| 298 | 
            +
                it 'should raise ArgumentError if column is a key' do
         | 
| 299 | 
            +
                  expect { Post.where(:permalink, 'cequel0') }.
         | 
| 300 | 
            +
                    to raise_error(ArgumentError)
         | 
| 301 | 
            +
                end
         | 
| 302 | 
            +
             | 
| 303 | 
            +
                it 'should raise IllegalQuery if applied twice' do
         | 
| 304 | 
            +
                  expect { Post.where(:author_id, uuids.first).
         | 
| 305 | 
            +
                    where(:author_name, 'Mat Brown') }.
         | 
| 306 | 
            +
                    to raise_error(Cequel::Model::IllegalQuery)
         | 
| 307 | 
            +
                end
         | 
| 308 | 
            +
              end
         | 
| 309 | 
            +
             | 
| 279 310 | 
             
              describe '#count' do
         | 
| 280 311 | 
             
                it 'should count records' do
         | 
| 281 312 | 
             
                  Blog.count.should == 3
         | 
| @@ -20,7 +20,7 @@ describe Cequel::Model::Schema do | |
| 20 20 | 
             
              context 'new model with simple primary key' do
         | 
| 21 21 | 
             
                before { model.synchronize_schema }
         | 
| 22 22 |  | 
| 23 | 
            -
                its(: | 
| 23 | 
            +
                its(:partition_key_columns) { should == [Cequel::Schema::Column.new(:permalink, :text)] }
         | 
| 24 24 | 
             
                its(:data_columns) { should include(Cequel::Schema::Column.new(:title, :text)) }
         | 
| 25 25 | 
             
                its(:data_columns) { should include(Cequel::Schema::List.new(:categories, :text)) }
         | 
| 26 26 | 
             
                its(:data_columns) { should include(Cequel::Schema::Set.new(:tags, :text)) }
         | 
| @@ -0,0 +1,45 @@ | |
| 1 | 
            +
            require_relative 'spec_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Cequel::Model::SecondaryIndexes do
         | 
| 4 | 
            +
              model :Post do
         | 
| 5 | 
            +
                key :blog_subdomain, :text
         | 
| 6 | 
            +
                key :permalink, :text
         | 
| 7 | 
            +
                column :title, :text
         | 
| 8 | 
            +
                column :author_id, :uuid, :index => true
         | 
| 9 | 
            +
              end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
              let(:uuids) { Array.new(2) { CassandraCQL::UUID.new }}
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              let!(:posts) do
         | 
| 14 | 
            +
                3.times.map do |i|
         | 
| 15 | 
            +
                  Post.create! do |post|
         | 
| 16 | 
            +
                    post.blog_subdomain = 'bigdata'
         | 
| 17 | 
            +
                    post.permalink = "cequel#{i}"
         | 
| 18 | 
            +
                    post.title = "Cequel #{i}"
         | 
| 19 | 
            +
                    post.author_id = uuids[i%2]
         | 
| 20 | 
            +
                  end
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
              it 'should create secondary index in schema' do
         | 
| 25 | 
            +
                cequel.schema.read_table(:posts).data_columns.
         | 
| 26 | 
            +
                  find { |column| column.name == :author_id }.index_name.
         | 
| 27 | 
            +
                  should be
         | 
| 28 | 
            +
              end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
              it 'should expose scope to query by secondary index' do
         | 
| 31 | 
            +
                Post.with_author_id(uuids.first).map(&:permalink).
         | 
| 32 | 
            +
                  should == %w(cequel0 cequel2)
         | 
| 33 | 
            +
              end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
              it 'should expose method to retrieve first result by secondary index' do
         | 
| 36 | 
            +
                Post.find_by_author_id(uuids.first).should == posts.first
         | 
| 37 | 
            +
              end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
              it 'should expose method to eagerly retrieve all results by secondary index' do
         | 
| 40 | 
            +
                posts = Post.find_all_by_author_id(uuids.first)
         | 
| 41 | 
            +
                disallow_queries!
         | 
| 42 | 
            +
                posts.map(&:permalink).should == %w(cequel0 cequel2)
         | 
| 43 | 
            +
              end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
            end
         | 
| @@ -14,11 +14,11 @@ describe Cequel::Schema::TableReader do | |
| 14 14 | 
             
                end
         | 
| 15 15 |  | 
| 16 16 | 
             
                it 'should read name correctly' do
         | 
| 17 | 
            -
                  table. | 
| 17 | 
            +
                  table.partition_key_columns.first.name.should == :permalink
         | 
| 18 18 | 
             
                end
         | 
| 19 19 |  | 
| 20 20 | 
             
                it 'should read type correctly' do
         | 
| 21 | 
            -
                  table. | 
| 21 | 
            +
                  table.partition_key_columns.first.type.should be_a(Cequel::Type::Text)
         | 
| 22 22 | 
             
                end
         | 
| 23 23 |  | 
| 24 24 | 
             
                it 'should have no nonpartition keys' do
         | 
| @@ -38,11 +38,11 @@ describe Cequel::Schema::TableReader do | |
| 38 38 | 
             
                end
         | 
| 39 39 |  | 
| 40 40 | 
             
                it 'should read partition key name' do
         | 
| 41 | 
            -
                  table. | 
| 41 | 
            +
                  table.partition_key_columns.map(&:name).should == [:blog_subdomain]
         | 
| 42 42 | 
             
                end
         | 
| 43 43 |  | 
| 44 44 | 
             
                it 'should read partition key type' do
         | 
| 45 | 
            -
                  table. | 
| 45 | 
            +
                  table.partition_key_columns.map(&:type).should == [Cequel::Type::Text.instance]
         | 
| 46 46 | 
             
                end
         | 
| 47 47 |  | 
| 48 48 | 
             
                it 'should read non-partition key name' do
         | 
| @@ -124,11 +124,11 @@ describe Cequel::Schema::TableReader do | |
| 124 124 | 
             
                end
         | 
| 125 125 |  | 
| 126 126 | 
             
                it 'should read partition key names' do
         | 
| 127 | 
            -
                  table. | 
| 127 | 
            +
                  table.partition_key_columns.map(&:name).should == [:blog_subdomain, :permalink]
         | 
| 128 128 | 
             
                end
         | 
| 129 129 |  | 
| 130 130 | 
             
                it 'should read partition key types' do
         | 
| 131 | 
            -
                  table. | 
| 131 | 
            +
                  table.partition_key_columns.map(&:type).
         | 
| 132 132 | 
             
                    should == [Cequel::Type::Text.instance, Cequel::Type::Ascii.instance]
         | 
| 133 133 | 
             
                end
         | 
| 134 134 |  | 
| @@ -153,11 +153,11 @@ describe Cequel::Schema::TableReader do | |
| 153 153 | 
             
                end
         | 
| 154 154 |  | 
| 155 155 | 
             
                it 'should read partition key names' do
         | 
| 156 | 
            -
                  table. | 
| 156 | 
            +
                  table.partition_key_columns.map(&:name).should == [:blog_subdomain, :permalink]
         | 
| 157 157 | 
             
                end
         | 
| 158 158 |  | 
| 159 159 | 
             
                it 'should read partition key types' do
         | 
| 160 | 
            -
                  table. | 
| 160 | 
            +
                  table.partition_key_columns.map(&:type).
         | 
| 161 161 | 
             
                    should == [Cequel::Type::Text.instance, Cequel::Type::Ascii.instance]
         | 
| 162 162 | 
             
                end
         | 
| 163 163 |  | 
| @@ -19,11 +19,11 @@ describe Cequel::Schema::TableWriter do | |
| 19 19 | 
             
                  end
         | 
| 20 20 |  | 
| 21 21 | 
             
                  it 'should create key alias' do
         | 
| 22 | 
            -
                    table. | 
| 22 | 
            +
                    table.partition_key_columns.map(&:name).should == [:permalink]
         | 
| 23 23 | 
             
                  end
         | 
| 24 24 |  | 
| 25 25 | 
             
                  it 'should set key validator' do
         | 
| 26 | 
            -
                    table. | 
| 26 | 
            +
                    table.partition_key_columns.map(&:type).should == [Cequel::Type[:ascii]]
         | 
| 27 27 | 
             
                  end
         | 
| 28 28 |  | 
| 29 29 | 
             
                  it 'should set non-key columns' do
         | 
| @@ -42,11 +42,11 @@ describe Cequel::Schema::TableWriter do | |
| 42 42 | 
             
                  end
         | 
| 43 43 |  | 
| 44 44 | 
             
                  it 'should create key alias' do
         | 
| 45 | 
            -
                    table. | 
| 45 | 
            +
                    table.partition_key_columns.map(&:name).should == [:blog_subdomain]
         | 
| 46 46 | 
             
                  end
         | 
| 47 47 |  | 
| 48 48 | 
             
                  it 'should set key validator' do
         | 
| 49 | 
            -
                    table. | 
| 49 | 
            +
                    table.partition_key_columns.map(&:type).should == [Cequel::Type[:ascii]]
         | 
| 50 50 | 
             
                  end
         | 
| 51 51 |  | 
| 52 52 | 
             
                  it 'should create non-partition key components' do
         | 
| @@ -68,11 +68,11 @@ describe Cequel::Schema::TableWriter do | |
| 68 68 | 
             
                  end
         | 
| 69 69 |  | 
| 70 70 | 
             
                  it 'should create all partition key components' do
         | 
| 71 | 
            -
                    table. | 
| 71 | 
            +
                    table.partition_key_columns.map(&:name).should == [:blog_subdomain, :permalink]
         | 
| 72 72 | 
             
                  end
         | 
| 73 73 |  | 
| 74 74 | 
             
                  it 'should set key validators' do
         | 
| 75 | 
            -
                    table. | 
| 75 | 
            +
                    table.partition_key_columns.map(&:type).
         | 
| 76 76 | 
             
                      should == [Cequel::Type[:ascii], Cequel::Type[:ascii]]
         | 
| 77 77 | 
             
                  end
         | 
| 78 78 | 
             
                end
         | 
| @@ -88,12 +88,12 @@ describe Cequel::Schema::TableWriter do | |
| 88 88 | 
             
                  end
         | 
| 89 89 |  | 
| 90 90 | 
             
                  it 'should create all partition key components' do
         | 
| 91 | 
            -
                    table. | 
| 91 | 
            +
                    table.partition_key_columns.map(&:name).
         | 
| 92 92 | 
             
                      should == [:blog_subdomain, :permalink]
         | 
| 93 93 | 
             
                  end
         | 
| 94 94 |  | 
| 95 95 | 
             
                  it 'should set key validators' do
         | 
| 96 | 
            -
                    table. | 
| 96 | 
            +
                    table.partition_key_columns.map(&:type).
         | 
| 97 97 | 
             
                      should == [Cequel::Type[:ascii], Cequel::Type[:ascii]]
         | 
| 98 98 | 
             
                  end
         | 
| 99 99 |  | 
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: cequel
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 1.0.0.pre. | 
| 4 | 
            +
              version: 1.0.0.pre.2
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Mat Brown
         | 
| @@ -11,7 +11,7 @@ authors: | |
| 11 11 | 
             
            autorequire: 
         | 
| 12 12 | 
             
            bindir: bin
         | 
| 13 13 | 
             
            cert_chain: []
         | 
| 14 | 
            -
            date: 2013-09- | 
| 14 | 
            +
            date: 2013-09-21 00:00:00.000000000 Z
         | 
| 15 15 | 
             
            dependencies:
         | 
| 16 16 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 17 17 | 
             
              name: activesupport
         | 
| @@ -126,9 +126,10 @@ dependencies: | |
| 126 126 | 
             
                  - !ruby/object:Gem::Version
         | 
| 127 127 | 
             
                    version: '0.6'
         | 
| 128 128 | 
             
            description: |
         | 
| 129 | 
            -
              Cequel is  | 
| 130 | 
            -
               | 
| 131 | 
            -
               | 
| 129 | 
            +
              Cequel is an ActiveRecord-like domain model layer for Cassandra that exposes
         | 
| 130 | 
            +
              the robust data modeling capabilities of CQL3, including parent-child
         | 
| 131 | 
            +
              relationships via compound primary keys and in-memory atomic manipulation of
         | 
| 132 | 
            +
              collection columns.
         | 
| 132 133 | 
             
            email: mat.a.brown@gmail.com
         | 
| 133 134 | 
             
            executables: []
         | 
| 134 135 | 
             
            extensions: []
         | 
| @@ -154,6 +155,7 @@ files: | |
| 154 155 | 
             
            - lib/cequel/model/belongs_to_association.rb
         | 
| 155 156 | 
             
            - lib/cequel/model/callbacks.rb
         | 
| 156 157 | 
             
            - lib/cequel/model/collection.rb
         | 
| 158 | 
            +
            - lib/cequel/model/dirty.rb
         | 
| 157 159 | 
             
            - lib/cequel/model/errors.rb
         | 
| 158 160 | 
             
            - lib/cequel/model/has_many_association.rb
         | 
| 159 161 | 
             
            - lib/cequel/model/mass_assignment.rb
         | 
| @@ -163,6 +165,7 @@ files: | |
| 163 165 | 
             
            - lib/cequel/model/record_set.rb
         | 
| 164 166 | 
             
            - lib/cequel/model/schema.rb
         | 
| 165 167 | 
             
            - lib/cequel/model/scoped.rb
         | 
| 168 | 
            +
            - lib/cequel/model/secondary_indexes.rb
         | 
| 166 169 | 
             
            - lib/cequel/model/validations.rb
         | 
| 167 170 | 
             
            - lib/cequel/model.rb
         | 
| 168 171 | 
             
            - lib/cequel/new_relic_instrumentation.rb
         | 
| @@ -178,12 +181,14 @@ files: | |
| 178 181 | 
             
            - lib/cequel/schema/update_table_dsl.rb
         | 
| 179 182 | 
             
            - lib/cequel/schema.rb
         | 
| 180 183 | 
             
            - lib/cequel/type.rb
         | 
| 184 | 
            +
            - lib/cequel/util.rb
         | 
| 181 185 | 
             
            - lib/cequel/version.rb
         | 
| 182 186 | 
             
            - lib/cequel.rb
         | 
| 183 187 | 
             
            - spec/environment.rb
         | 
| 184 188 | 
             
            - spec/examples/metal/data_set_spec.rb
         | 
| 185 189 | 
             
            - spec/examples/model/associations_spec.rb
         | 
| 186 190 | 
             
            - spec/examples/model/callbacks_spec.rb
         | 
| 191 | 
            +
            - spec/examples/model/dirty_spec.rb
         | 
| 187 192 | 
             
            - spec/examples/model/list_spec.rb
         | 
| 188 193 | 
             
            - spec/examples/model/map_spec.rb
         | 
| 189 194 | 
             
            - spec/examples/model/mass_assignment_spec.rb
         | 
| @@ -192,6 +197,7 @@ files: | |
| 192 197 | 
             
            - spec/examples/model/properties_spec.rb
         | 
| 193 198 | 
             
            - spec/examples/model/record_set_spec.rb
         | 
| 194 199 | 
             
            - spec/examples/model/schema_spec.rb
         | 
| 200 | 
            +
            - spec/examples/model/secondary_index_spec.rb
         | 
| 195 201 | 
             
            - spec/examples/model/serialization_spec.rb
         | 
| 196 202 | 
             
            - spec/examples/model/set_spec.rb
         | 
| 197 203 | 
             
            - spec/examples/model/spec_helper.rb
         | 
| @@ -240,11 +246,12 @@ rubyforge_project: | |
| 240 246 | 
             
            rubygems_version: 2.0.3
         | 
| 241 247 | 
             
            signing_key: 
         | 
| 242 248 | 
             
            specification_version: 4
         | 
| 243 | 
            -
            summary:  | 
| 249 | 
            +
            summary: Full-featured, ActiveModel-compliant ORM for Cassandra using CQL3
         | 
| 244 250 | 
             
            test_files:
         | 
| 245 251 | 
             
            - spec/examples/metal/data_set_spec.rb
         | 
| 246 252 | 
             
            - spec/examples/model/associations_spec.rb
         | 
| 247 253 | 
             
            - spec/examples/model/callbacks_spec.rb
         | 
| 254 | 
            +
            - spec/examples/model/dirty_spec.rb
         | 
| 248 255 | 
             
            - spec/examples/model/list_spec.rb
         | 
| 249 256 | 
             
            - spec/examples/model/map_spec.rb
         | 
| 250 257 | 
             
            - spec/examples/model/mass_assignment_spec.rb
         | 
| @@ -253,6 +260,7 @@ test_files: | |
| 253 260 | 
             
            - spec/examples/model/properties_spec.rb
         | 
| 254 261 | 
             
            - spec/examples/model/record_set_spec.rb
         | 
| 255 262 | 
             
            - spec/examples/model/schema_spec.rb
         | 
| 263 | 
            +
            - spec/examples/model/secondary_index_spec.rb
         | 
| 256 264 | 
             
            - spec/examples/model/serialization_spec.rb
         | 
| 257 265 | 
             
            - spec/examples/model/set_spec.rb
         | 
| 258 266 | 
             
            - spec/examples/model/spec_helper.rb
         |