datastax_rails 1.2.3 → 2.0.3

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 (104) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE +1 -1
  3. data/README.rdoc +20 -8
  4. data/config/schema.xml.erb +22 -19
  5. data/config/solrconfig.xml.erb +1 -1
  6. data/lib/cql-rb_extensions.rb +27 -0
  7. data/lib/datastax_rails.rb +13 -17
  8. data/lib/datastax_rails/associations/association.rb +1 -4
  9. data/lib/datastax_rails/associations/collection_proxy.rb +0 -13
  10. data/lib/datastax_rails/attribute_assignment.rb +28 -91
  11. data/lib/datastax_rails/attribute_methods.rb +109 -44
  12. data/lib/datastax_rails/attribute_methods/before_type_cast.rb +71 -0
  13. data/lib/datastax_rails/attribute_methods/dirty.rb +52 -11
  14. data/lib/datastax_rails/attribute_methods/primary_key.rb +87 -0
  15. data/lib/datastax_rails/attribute_methods/read.rb +120 -0
  16. data/lib/datastax_rails/attribute_methods/typecasting.rb +52 -21
  17. data/lib/datastax_rails/attribute_methods/write.rb +59 -0
  18. data/lib/datastax_rails/base.rb +227 -236
  19. data/lib/datastax_rails/cassandra_only_model.rb +25 -19
  20. data/lib/datastax_rails/column.rb +384 -0
  21. data/lib/datastax_rails/connection.rb +12 -13
  22. data/lib/datastax_rails/cql/alter_column_family.rb +0 -1
  23. data/lib/datastax_rails/cql/base.rb +15 -3
  24. data/lib/datastax_rails/cql/column_family.rb +2 -2
  25. data/lib/datastax_rails/cql/create_column_family.rb +7 -18
  26. data/lib/datastax_rails/cql/delete.rb +4 -9
  27. data/lib/datastax_rails/cql/insert.rb +2 -8
  28. data/lib/datastax_rails/cql/select.rb +4 -4
  29. data/lib/datastax_rails/cql/update.rb +8 -17
  30. data/lib/datastax_rails/dynamic_model.rb +98 -0
  31. data/lib/datastax_rails/payload_model.rb +19 -31
  32. data/lib/datastax_rails/persistence.rb +39 -54
  33. data/lib/datastax_rails/railtie.rb +1 -0
  34. data/lib/datastax_rails/reflection.rb +1 -1
  35. data/lib/datastax_rails/relation.rb +20 -20
  36. data/lib/datastax_rails/relation/batches.rb +18 -16
  37. data/lib/datastax_rails/relation/facet_methods.rb +1 -1
  38. data/lib/datastax_rails/relation/finder_methods.rb +6 -10
  39. data/lib/datastax_rails/relation/search_methods.rb +62 -48
  40. data/lib/datastax_rails/rsolr_client_wrapper.rb +1 -1
  41. data/lib/datastax_rails/schema/cassandra.rb +34 -62
  42. data/lib/datastax_rails/schema/migrator.rb +9 -24
  43. data/lib/datastax_rails/schema/solr.rb +13 -30
  44. data/lib/datastax_rails/schema_cache.rb +67 -0
  45. data/lib/datastax_rails/timestamps.rb +84 -11
  46. data/lib/datastax_rails/types/dirty_collection.rb +88 -0
  47. data/lib/datastax_rails/types/dynamic_list.rb +14 -0
  48. data/lib/datastax_rails/types/dynamic_map.rb +32 -0
  49. data/lib/datastax_rails/types/dynamic_set.rb +10 -0
  50. data/lib/datastax_rails/util/solr_repair.rb +4 -5
  51. data/lib/datastax_rails/validations.rb +6 -12
  52. data/lib/datastax_rails/validations/uniqueness.rb +0 -4
  53. data/lib/datastax_rails/version.rb +1 -1
  54. data/lib/datastax_rails/wide_storage_model.rb +13 -29
  55. data/lib/schema_migration.rb +4 -0
  56. data/spec/datastax_rails/associations_spec.rb +0 -1
  57. data/spec/datastax_rails/attribute_methods_spec.rb +9 -6
  58. data/spec/datastax_rails/base_spec.rb +26 -0
  59. data/spec/datastax_rails/column_spec.rb +238 -0
  60. data/spec/datastax_rails/cql/select_spec.rb +1 -1
  61. data/spec/datastax_rails/cql/update_spec.rb +2 -2
  62. data/spec/datastax_rails/persistence_spec.rb +29 -15
  63. data/spec/datastax_rails/relation/batches_spec.rb +5 -5
  64. data/spec/datastax_rails/relation/finder_methods_spec.rb +0 -20
  65. data/spec/datastax_rails/relation/search_methods_spec.rb +8 -0
  66. data/spec/datastax_rails/relation_spec.rb +7 -0
  67. data/spec/datastax_rails/schema/migrator_spec.rb +5 -10
  68. data/spec/datastax_rails/schema/solr_spec.rb +1 -1
  69. data/spec/datastax_rails/types/dynamic_list_spec.rb +20 -0
  70. data/spec/datastax_rails/types/dynamic_map_spec.rb +22 -0
  71. data/spec/datastax_rails/types/dynamic_set_spec.rb +16 -0
  72. data/spec/dummy/config/application.rb +2 -1
  73. data/spec/dummy/config/datastax.yml +6 -3
  74. data/spec/dummy/config/environments/development.rb +4 -5
  75. data/spec/dummy/config/environments/test.rb +0 -5
  76. data/spec/dummy/log/development.log +18 -0
  77. data/spec/dummy/log/test.log +36 -0
  78. data/spec/feature/dynamic_fields_spec.rb +9 -0
  79. data/spec/feature/overloaded_tables_spec.rb +24 -0
  80. data/spec/spec_helper.rb +1 -1
  81. data/spec/support/default_consistency_shared_examples.rb +2 -2
  82. data/spec/support/models.rb +28 -14
  83. metadata +212 -188
  84. data/lib/datastax_rails/identity.rb +0 -64
  85. data/lib/datastax_rails/identity/abstract_key_factory.rb +0 -29
  86. data/lib/datastax_rails/identity/custom_key_factory.rb +0 -37
  87. data/lib/datastax_rails/identity/hashed_natural_key_factory.rb +0 -10
  88. data/lib/datastax_rails/identity/natural_key_factory.rb +0 -39
  89. data/lib/datastax_rails/identity/uuid_key_factory.rb +0 -27
  90. data/lib/datastax_rails/type.rb +0 -16
  91. data/lib/datastax_rails/types.rb +0 -9
  92. data/lib/datastax_rails/types/array_type.rb +0 -86
  93. data/lib/datastax_rails/types/base_type.rb +0 -42
  94. data/lib/datastax_rails/types/binary_type.rb +0 -19
  95. data/lib/datastax_rails/types/boolean_type.rb +0 -22
  96. data/lib/datastax_rails/types/date_type.rb +0 -23
  97. data/lib/datastax_rails/types/float_type.rb +0 -18
  98. data/lib/datastax_rails/types/integer_type.rb +0 -18
  99. data/lib/datastax_rails/types/string_type.rb +0 -16
  100. data/lib/datastax_rails/types/text_type.rb +0 -15
  101. data/lib/datastax_rails/types/time_type.rb +0 -23
  102. data/spec/datastax_rails/types/float_type_spec.rb +0 -31
  103. data/spec/datastax_rails/types/integer_type_spec.rb +0 -31
  104. data/spec/datastax_rails/types/time_type_spec.rb +0 -28
@@ -1,64 +0,0 @@
1
- module DatastaxRails #:nodoc:
2
- module Identity
3
- extend ActiveSupport::Concern
4
- extend ActiveSupport::Autoload
5
-
6
- autoload :Key
7
- autoload :AbstractKeyFactory
8
- autoload :UUIDKeyFactory
9
- autoload :NaturalKeyFactory
10
- autoload :HashedNaturalKeyFactory
11
- autoload :CustomKeyFactory
12
-
13
- module ClassMethods
14
- attr_accessor :key_factory
15
- # Indicate what kind of key the model will have: uuid or natural
16
- #
17
- # @param [:uuid, :natural] name_or_factory the type of key
18
- # @param [Hash] options the options you want to pass along to the key factory (like :attributes => :name, for a natural key).
19
- #
20
- def key(name_or_factory = :uuid, *options)
21
- @key_factory = case name_or_factory
22
- when :uuid
23
- UUIDKeyFactory.new(*options)
24
- when :natural
25
- NaturalKeyFactory.new(*options)
26
- when :custom
27
- CustomKeyFactory.new(*options)
28
- else
29
- name_or_factory
30
- end
31
- end
32
-
33
- # The next key for the given object. Delegates the actual work to the factory which may
34
- # or may not use the passed in object to generate the key.
35
- #
36
- # @param [DatastaxRails::Base] object the object for which the key is being generated
37
- # @return [String] a key for this object
38
- def next_key(object = nil)
39
- @key_factory.next_key(object).tap do |key|
40
- raise "Keys may not be nil" if key.nil?
41
- end
42
- end
43
-
44
- # Parses out a key from the given string. Delegates the actual work to the factory.
45
- # Return type varies depending on what type of key is used.
46
- #
47
- # @param [String] string a string representing a primary key
48
- # @return an object representing the same key
49
- def parse_key(string)
50
- @key_factory.parse(string)
51
- end
52
- end
53
-
54
- def id
55
- key.to_s
56
- end
57
-
58
- # TODO test this
59
- def id=(key)
60
- self.key = self.class.parse_key(key)
61
- id
62
- end
63
- end
64
- end
@@ -1,29 +0,0 @@
1
- module DatastaxRails
2
- module Identity
3
- # Key factories need to support 3 operations
4
- class AbstractKeyFactory
5
- attr_accessor :key_columns
6
- # Next key takes an object and returns the key object it should use.
7
- # object will be ignored with synthetic keys but could be useful with natural ones
8
- #
9
- # @abstract
10
- # @param [DatastaxRails::Base] object the object that needs a new key
11
- # @return [DatastaxRails::Identity::Key] the key
12
- #
13
- def next_key(object)
14
- raise NotImplementedError, "#{self.class.name}#next_key isn't implemented."
15
- end
16
-
17
- # Parse should create a new key object from the 'to_param' format
18
- #
19
- # @abstract
20
- # @param [String] string the result of calling key.to_param
21
- # @return [DatastaxRails::Identity::Key] the parsed key
22
- #
23
- def parse(string)
24
- raise NotImplementedError, "#{self.class.name}#parse isn't implemented."
25
- end
26
- end
27
- end
28
- end
29
-
@@ -1,37 +0,0 @@
1
- module DatastaxRails
2
- module Identity
3
- class CustomKeyFactory < AbstractKeyFactory
4
- class CustomKey
5
- attr_reader :value
6
-
7
- def initialize(value)
8
- @value = value
9
- end
10
-
11
- def to_s
12
- value
13
- end
14
-
15
- def ==(other)
16
- other.to_s == value
17
- end
18
- end
19
-
20
- attr_reader :method
21
-
22
- def initialize(options)
23
- @method = options[:method]
24
- @key_columns = Array.wrap(options[:column])
25
- end
26
-
27
- def next_key(object)
28
- CustomKey.new(object.send(@method))
29
- end
30
-
31
- def parse(value)
32
- value
33
- end
34
- end
35
- end
36
- end
37
-
@@ -1,10 +0,0 @@
1
- require 'digest/sha1'
2
- module DatastaxRails
3
- module Identity
4
- class HashedNaturalKeyFactory < NaturalKeyFactory
5
- def next_key(object)
6
- NaturalKey.new(Digest::SHA1.hexdigest(attributes.map { |a| object.attributes[a.to_s] }.join(separator)))
7
- end
8
- end
9
- end
10
- end
@@ -1,39 +0,0 @@
1
- module DatastaxRails
2
- module Identity
3
- class NaturalKeyFactory < AbstractKeyFactory
4
- class NaturalKey
5
- attr_reader :value
6
-
7
- delegate :size, :bytesize, :to => :value
8
- def initialize(value)
9
- @value = value
10
- end
11
-
12
- def to_s
13
- value
14
- end
15
-
16
- def ==(other)
17
- other.to_s == to_s
18
- end
19
- end
20
-
21
- attr_reader :attributes, :separator
22
-
23
- def initialize(options)
24
- @attributes = [*options[:attributes]]
25
- @separator = options[:separator] || "-"
26
- @key_columns = options[:column].blank? ? @attributes.dup : Array.wrap(options[:column])
27
- end
28
-
29
- def next_key(object)
30
- NaturalKey.new(attributes.map { |a| object.attributes[a.to_s] }.join(separator))
31
- end
32
-
33
- def parse(paramized_key)
34
- NaturalKey.new(paramized_key)
35
- end
36
- end
37
- end
38
- end
39
-
@@ -1,27 +0,0 @@
1
- module DatastaxRails
2
- module Identity
3
- # Key factories need to support 3 operations
4
- class UUIDKeyFactory < AbstractKeyFactory
5
- class UUID < SimpleUUID::UUID
6
- def to_s
7
- to_guid
8
- end
9
- end
10
-
11
- def initialize(options = {})
12
- @key_columns = options[:column].blank? ? ['key'] : Array.wrap(options[:column])
13
- end
14
-
15
- def next_key(object)
16
- UUID.new
17
- end
18
-
19
- def parse(string)
20
- UUID.new(string) if string
21
- rescue
22
- nil
23
- end
24
- end
25
- end
26
- end
27
-
@@ -1,16 +0,0 @@
1
- module DatastaxRails
2
- class Type
3
- cattr_accessor :attribute_types
4
- self.attribute_types = {}.with_indifferent_access
5
-
6
- class << self
7
- def register(name, coder)
8
- attribute_types[name] = coder
9
- end
10
-
11
- def get_coder(name)
12
- attribute_types[name]
13
- end
14
- end
15
- end
16
- end
@@ -1,9 +0,0 @@
1
- DatastaxRails::Type.register(:array, DatastaxRails::Types::ArrayType)
2
- DatastaxRails::Type.register(:binary, DatastaxRails::Types::BinaryType)
3
- DatastaxRails::Type.register(:boolean, DatastaxRails::Types::BooleanType)
4
- DatastaxRails::Type.register(:date, DatastaxRails::Types::DateType)
5
- DatastaxRails::Type.register(:float, DatastaxRails::Types::FloatType)
6
- DatastaxRails::Type.register(:integer, DatastaxRails::Types::IntegerType)
7
- DatastaxRails::Type.register(:time, DatastaxRails::Types::TimeType)
8
- DatastaxRails::Type.register(:string, DatastaxRails::Types::StringType)
9
- DatastaxRails::Type.register(:text, DatastaxRails::Types::TextType)
@@ -1,86 +0,0 @@
1
- module DatastaxRails
2
- module Types
3
- # ArrayType is used for storing arrays in Datastax Enterprise.
4
- # They are indexed into SOLR as discrete values so that you can do something like this:
5
- #
6
- # Post.where(:tags => 'Technology')
7
- #
8
- # That would give you all the posts that have Technology somewhere in the tags array.
9
- class ArrayType < BaseType
10
- DEFAULTS = {:solr_type => 'array', :indexed => :solr, :stored => true, :multi_valued => false, :sortable => false, :tokenized => true, :fulltext => true, :cassandra_type => 'text'}
11
-
12
- # An extension to normal arrays that allow for tracking of dirty values. This is
13
- # used by ActiveModel's change tracking framework.
14
- class DirtyArray < Array
15
- attr_accessor :record, :name, :options
16
- def initialize(record, name, array, options)
17
- @record = record
18
- @name = name.to_s
19
- @options = options
20
-
21
- super(array)
22
- setify!
23
- end
24
-
25
- def <<(obj)
26
- modifying do
27
- super
28
- setify!
29
- end
30
- end
31
-
32
- def delete(obj)
33
- modifying do
34
- super
35
- end
36
- end
37
-
38
- private
39
- def setify!
40
- if options[:unique]
41
- compact!
42
- uniq!
43
- begin sort! rescue ArgumentError end
44
- end
45
- end
46
-
47
- def modifying
48
- unless record.changed_attributes.include?(name)
49
- original = dup
50
- end
51
-
52
- result = yield
53
-
54
- if !record.changed_attributes.key?(name) && original != self
55
- record.changed_attributes[name] = original
56
- end
57
-
58
- record.send("#{name}=", self)
59
-
60
- result
61
- end
62
- end
63
-
64
- def default
65
- []
66
- end
67
-
68
- def encode(array)
69
- raise ArgumentError.new("#{self} requires an Array") unless array.kind_of?(Array)
70
- ar = Array(array)
71
- ar.uniq! if options[:unique]
72
- ar.join("$$$$")
73
- end
74
-
75
- def decode(str)
76
- return [] if str.blank?
77
- # Temporary fix
78
- str.is_a?(Array) ? str.flatten : str.gsub(/&&&&/,'$$$$').split(/\$\$\$\$/).reject{|a|a.blank?}
79
- end
80
-
81
- def wrap(record, name, value)
82
- DirtyArray.new(record, name, value, options)
83
- end
84
- end
85
- end
86
- end
@@ -1,42 +0,0 @@
1
- module DatastaxRails
2
- module Types
3
- # All of the DSR type classes inherit from here. It sets up some default options and doesn basic conversion
4
- # to strings. Subclasses can override these methods as needed.
5
- #
6
- # NOTE: All subclasses MUST declare a +DEFAULTS+ constant that specifies the indexing defaults. Defaults may of
7
- # course be overridden when the attribute is declared.
8
- class BaseType
9
- attr_accessor :options
10
- # Default initializer. Sets the indexing options based on the DEFAULTS
11
- def initialize(options = {})
12
- @options = self.class::DEFAULTS.merge(options)
13
- end
14
-
15
- def default
16
- if options.has_key?(:default)
17
- options[:default].duplicable? ? options[:default].dup : options[:default]
18
- end
19
- end
20
-
21
- def encode(value, format = :solr)
22
- value.to_s
23
- end
24
-
25
- def decode(str)
26
- str
27
- end
28
-
29
- def wrap(record, name, value)
30
- value
31
- end
32
-
33
- def type
34
- self.class.name.sub(/^DatastaxRails::Types::/,'').sub(/Type$/,'').underscore.to_sym
35
- end
36
-
37
- def full_solr_range
38
- '[\"\" TO *]'
39
- end
40
- end
41
- end
42
- end
@@ -1,19 +0,0 @@
1
- module DatastaxRails
2
- module Types
3
- class BinaryType < BaseType
4
- DEFAULTS = {:solr_type => false, :indexed => false, :stored => false, :multi_valued => false, :sortable => false, :tokenized => false, :fulltext => false, :cassandra_type => 'blob'}
5
- def encode(str)
6
- raise ArgumentError.new("#{self} requires a String") unless str.kind_of?(String)
7
- Base64.encode64(str)
8
- end
9
-
10
- def decode(str)
11
- Base64.decode64(str)
12
- end
13
-
14
- def wrap(record, name, value)
15
- (value.frozen? ? value.dup : value)
16
- end
17
- end
18
- end
19
- end
@@ -1,22 +0,0 @@
1
- module DatastaxRails
2
- module Types
3
- class BooleanType < BaseType
4
- DEFAULTS = {:solr_type => 'boolean', :indexed => :solr, :stored => true, :multi_valued => false, :sortable => true, :tokenized => false, :fulltext => false, :cassandra_type => 'boolean'}
5
- TRUE_VALS = [true, 'true', '1', 'Y']
6
- FALSE_VALS = [false, 'false', '0', '', 'N', nil, 'null']
7
- VALID_VALS = TRUE_VALS + FALSE_VALS
8
-
9
- def encode(bool)
10
- unless VALID_VALS.include?(bool)
11
- raise ArgumentError.new("#{self} requires a boolean")
12
- end
13
- TRUE_VALS.include?(bool) ? '1' : '0'
14
- end
15
-
16
- def decode(str)
17
- raise ArgumentError.new("Cannot convert #{str} into a boolean") unless VALID_VALS.include?(str)
18
- TRUE_VALS.include?(str)
19
- end
20
- end
21
- end
22
- end
@@ -1,23 +0,0 @@
1
- module DatastaxRails
2
- module Types
3
- class DateType < BaseType
4
- DEFAULTS = {:solr_type => 'date', :indexed => :solr, :stored => true, :multi_valued => false, :sortable => true, :tokenized => false, :fulltext => false, :cassandra_type => 'timestamp'}
5
- FORMAT = '%Y-%m-%dT%H:%M:%SZ'
6
-
7
- def encode(value)
8
- return unless value
9
- raise ArgumentError.new("#{self} requires a Date") unless value.kind_of?(Date) || value.kind_of?(Time)
10
- value.to_date.strftime(FORMAT)
11
- end
12
-
13
- def decode(str)
14
- return str if str.kind_of?(Date)
15
- Date.parse(str) rescue nil
16
- end
17
-
18
- def full_solr_range
19
- '[* TO *]'
20
- end
21
- end
22
- end
23
- end