datastax_rails 1.0.5

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 (148) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.rdoc +62 -0
  3. data/Rakefile +34 -0
  4. data/config/schema.xml +266 -0
  5. data/config/schema.xml.erb +70 -0
  6. data/config/solrconfig.xml +1564 -0
  7. data/config/stopwords.txt +58 -0
  8. data/lib/datastax_rails/associations/association.rb +224 -0
  9. data/lib/datastax_rails/associations/association_scope.rb +25 -0
  10. data/lib/datastax_rails/associations/belongs_to_association.rb +64 -0
  11. data/lib/datastax_rails/associations/builder/association.rb +56 -0
  12. data/lib/datastax_rails/associations/builder/belongs_to.rb +30 -0
  13. data/lib/datastax_rails/associations/builder/collection_association.rb +48 -0
  14. data/lib/datastax_rails/associations/builder/has_and_belongs_to_many.rb +36 -0
  15. data/lib/datastax_rails/associations/builder/has_many.rb +54 -0
  16. data/lib/datastax_rails/associations/builder/has_one.rb +52 -0
  17. data/lib/datastax_rails/associations/builder/singular_association.rb +56 -0
  18. data/lib/datastax_rails/associations/collection_association.rb +274 -0
  19. data/lib/datastax_rails/associations/collection_proxy.rb +118 -0
  20. data/lib/datastax_rails/associations/has_and_belongs_to_many_association.rb +44 -0
  21. data/lib/datastax_rails/associations/has_many_association.rb +58 -0
  22. data/lib/datastax_rails/associations/has_one_association.rb +68 -0
  23. data/lib/datastax_rails/associations/singular_association.rb +58 -0
  24. data/lib/datastax_rails/associations.rb +86 -0
  25. data/lib/datastax_rails/attribute_methods/definition.rb +20 -0
  26. data/lib/datastax_rails/attribute_methods/dirty.rb +43 -0
  27. data/lib/datastax_rails/attribute_methods/typecasting.rb +50 -0
  28. data/lib/datastax_rails/attribute_methods.rb +104 -0
  29. data/lib/datastax_rails/base.rb +587 -0
  30. data/lib/datastax_rails/batches.rb +35 -0
  31. data/lib/datastax_rails/callbacks.rb +37 -0
  32. data/lib/datastax_rails/collection.rb +9 -0
  33. data/lib/datastax_rails/connection.rb +21 -0
  34. data/lib/datastax_rails/consistency.rb +33 -0
  35. data/lib/datastax_rails/cql/base.rb +15 -0
  36. data/lib/datastax_rails/cql/column_family.rb +38 -0
  37. data/lib/datastax_rails/cql/consistency.rb +13 -0
  38. data/lib/datastax_rails/cql/create_column_family.rb +63 -0
  39. data/lib/datastax_rails/cql/create_keyspace.rb +30 -0
  40. data/lib/datastax_rails/cql/delete.rb +41 -0
  41. data/lib/datastax_rails/cql/drop_column_family.rb +13 -0
  42. data/lib/datastax_rails/cql/drop_keyspace.rb +13 -0
  43. data/lib/datastax_rails/cql/insert.rb +53 -0
  44. data/lib/datastax_rails/cql/select.rb +51 -0
  45. data/lib/datastax_rails/cql/truncate.rb +13 -0
  46. data/lib/datastax_rails/cql/update.rb +68 -0
  47. data/lib/datastax_rails/cql/use_keyspace.rb +13 -0
  48. data/lib/datastax_rails/cql.rb +25 -0
  49. data/lib/datastax_rails/cursor.rb +90 -0
  50. data/lib/datastax_rails/errors.rb +16 -0
  51. data/lib/datastax_rails/identity/abstract_key_factory.rb +26 -0
  52. data/lib/datastax_rails/identity/custom_key_factory.rb +36 -0
  53. data/lib/datastax_rails/identity/hashed_natural_key_factory.rb +10 -0
  54. data/lib/datastax_rails/identity/natural_key_factory.rb +37 -0
  55. data/lib/datastax_rails/identity/uuid_key_factory.rb +23 -0
  56. data/lib/datastax_rails/identity.rb +53 -0
  57. data/lib/datastax_rails/log_subscriber.rb +37 -0
  58. data/lib/datastax_rails/migrations/migration.rb +15 -0
  59. data/lib/datastax_rails/migrations.rb +36 -0
  60. data/lib/datastax_rails/mocking.rb +15 -0
  61. data/lib/datastax_rails/persistence.rb +133 -0
  62. data/lib/datastax_rails/railtie.rb +20 -0
  63. data/lib/datastax_rails/reflection.rb +472 -0
  64. data/lib/datastax_rails/relation/finder_methods.rb +184 -0
  65. data/lib/datastax_rails/relation/modification_methods.rb +80 -0
  66. data/lib/datastax_rails/relation/search_methods.rb +349 -0
  67. data/lib/datastax_rails/relation/spawn_methods.rb +107 -0
  68. data/lib/datastax_rails/relation.rb +393 -0
  69. data/lib/datastax_rails/schema/migration.rb +106 -0
  70. data/lib/datastax_rails/schema/migration_proxy.rb +25 -0
  71. data/lib/datastax_rails/schema/migrator.rb +212 -0
  72. data/lib/datastax_rails/schema.rb +37 -0
  73. data/lib/datastax_rails/scoping.rb +394 -0
  74. data/lib/datastax_rails/serialization.rb +6 -0
  75. data/lib/datastax_rails/tasks/column_family.rb +162 -0
  76. data/lib/datastax_rails/tasks/ds.rake +63 -0
  77. data/lib/datastax_rails/tasks/keyspace.rb +57 -0
  78. data/lib/datastax_rails/timestamps.rb +19 -0
  79. data/lib/datastax_rails/type.rb +16 -0
  80. data/lib/datastax_rails/types/array_type.rb +77 -0
  81. data/lib/datastax_rails/types/base_type.rb +26 -0
  82. data/lib/datastax_rails/types/binary_type.rb +15 -0
  83. data/lib/datastax_rails/types/boolean_type.rb +22 -0
  84. data/lib/datastax_rails/types/date_type.rb +17 -0
  85. data/lib/datastax_rails/types/float_type.rb +18 -0
  86. data/lib/datastax_rails/types/integer_type.rb +18 -0
  87. data/lib/datastax_rails/types/string_type.rb +16 -0
  88. data/lib/datastax_rails/types/text_type.rb +16 -0
  89. data/lib/datastax_rails/types/time_type.rb +17 -0
  90. data/lib/datastax_rails/types.rb +9 -0
  91. data/lib/datastax_rails/validations/uniqueness.rb +119 -0
  92. data/lib/datastax_rails/validations.rb +48 -0
  93. data/lib/datastax_rails/version.rb +3 -0
  94. data/lib/datastax_rails.rb +87 -0
  95. data/lib/solr_no_escape.rb +28 -0
  96. data/spec/datastax_rails/associations/belongs_to_association_spec.rb +7 -0
  97. data/spec/datastax_rails/associations/has_many_association_spec.rb +37 -0
  98. data/spec/datastax_rails/associations_spec.rb +22 -0
  99. data/spec/datastax_rails/attribute_methods_spec.rb +23 -0
  100. data/spec/datastax_rails/base_spec.rb +15 -0
  101. data/spec/datastax_rails/cql/select_spec.rb +12 -0
  102. data/spec/datastax_rails/cql/update_spec.rb +0 -0
  103. data/spec/datastax_rails/relation/finder_methods_spec.rb +54 -0
  104. data/spec/datastax_rails/relation/modification_methods_spec.rb +41 -0
  105. data/spec/datastax_rails/relation/search_methods_spec.rb +117 -0
  106. data/spec/datastax_rails/relation/spawn_methods_spec.rb +28 -0
  107. data/spec/datastax_rails/relation_spec.rb +130 -0
  108. data/spec/datastax_rails/validations/uniqueness_spec.rb +41 -0
  109. data/spec/datastax_rails_spec.rb +5 -0
  110. data/spec/dummy/Rakefile +8 -0
  111. data/spec/dummy/app/assets/javascripts/application.js +9 -0
  112. data/spec/dummy/app/assets/stylesheets/application.css +7 -0
  113. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  114. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  115. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  116. data/spec/dummy/config/application.rb +47 -0
  117. data/spec/dummy/config/boot.rb +10 -0
  118. data/spec/dummy/config/database.yml +25 -0
  119. data/spec/dummy/config/datastax.yml +18 -0
  120. data/spec/dummy/config/environment.rb +5 -0
  121. data/spec/dummy/config/environments/development.rb +30 -0
  122. data/spec/dummy/config/environments/production.rb +60 -0
  123. data/spec/dummy/config/environments/test.rb +39 -0
  124. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  125. data/spec/dummy/config/initializers/inflections.rb +10 -0
  126. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  127. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  128. data/spec/dummy/config/initializers/session_store.rb +8 -0
  129. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  130. data/spec/dummy/config/locales/en.yml +5 -0
  131. data/spec/dummy/config/routes.rb +58 -0
  132. data/spec/dummy/config/sunspot.yml +17 -0
  133. data/spec/dummy/config.ru +4 -0
  134. data/spec/dummy/ks/migrate/20111117224534_models.rb +20 -0
  135. data/spec/dummy/ks/schema.json +180 -0
  136. data/spec/dummy/log/development.log +298 -0
  137. data/spec/dummy/log/production.log +0 -0
  138. data/spec/dummy/log/test.log +20307 -0
  139. data/spec/dummy/public/404.html +26 -0
  140. data/spec/dummy/public/422.html +26 -0
  141. data/spec/dummy/public/500.html +26 -0
  142. data/spec/dummy/public/favicon.ico +0 -0
  143. data/spec/dummy/script/rails +6 -0
  144. data/spec/spec.opts +5 -0
  145. data/spec/spec_helper.rb +29 -0
  146. data/spec/support/datastax_test_hook.rb +14 -0
  147. data/spec/support/models.rb +72 -0
  148. metadata +353 -0
@@ -0,0 +1,37 @@
1
+ module DatastaxRails
2
+ module Identity
3
+ class NaturalKeyFactory < AbstractKeyFactory
4
+ class NaturalKey
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 == to_s
17
+ end
18
+ end
19
+
20
+ attr_reader :attributes, :separator
21
+
22
+ def initialize(options)
23
+ @attributes = [*options[:attributes]]
24
+ @separator = options[:separator] || "-"
25
+ end
26
+
27
+ def next_key(object)
28
+ NaturalKey.new(attributes.map { |a| object.attributes[a.to_s] }.join(separator))
29
+ end
30
+
31
+ def parse(paramized_key)
32
+ NaturalKey.new(paramized_key)
33
+ end
34
+ end
35
+ end
36
+ end
37
+
@@ -0,0 +1,23 @@
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 next_key(object)
12
+ UUID.new
13
+ end
14
+
15
+ def parse(string)
16
+ UUID.new(string) if string
17
+ rescue
18
+ nil
19
+ end
20
+ end
21
+ end
22
+ end
23
+
@@ -0,0 +1,53 @@
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
+ # Indicate what kind of key the model will have: uuid or natural
15
+ #
16
+ # @param [:uuid, :natural] the type of key
17
+ # @param the options you want to pass along to the key factory (like :attributes => :name, for a natural key).
18
+ #
19
+ def key(name_or_factory = :uuid, *options)
20
+ @key_factory = case name_or_factory
21
+ when :uuid
22
+ UUIDKeyFactory.new
23
+ when :natural
24
+ NaturalKeyFactory.new(*options)
25
+ when :custom
26
+ CustomKeyFactory.new(*options)
27
+ else
28
+ name_or_factory
29
+ end
30
+ end
31
+
32
+ def next_key(object = nil)
33
+ @key_factory.next_key(object).tap do |key|
34
+ raise "Keys may not be nil" if key.nil?
35
+ end
36
+ end
37
+
38
+ def parse_key(string)
39
+ @key_factory.parse(string)
40
+ end
41
+ end
42
+
43
+ def id
44
+ key.to_s
45
+ end
46
+
47
+ # TODO test this
48
+ def id=(key)
49
+ self.key = self.class.parse_key(key)
50
+ id
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,37 @@
1
+ module DatastaxRails
2
+ class LogSubscriber < ActiveSupport::LogSubscriber
3
+ def multi_get(event)
4
+ name = '%s multi_get (%.1fms)' % [event.payload[:column_family], event.duration]
5
+
6
+ debug " #{name} (#{event.payload[:keys].size}) #{event.payload[:keys].join(" ")}"
7
+ end
8
+
9
+ def remove(event)
10
+ name = '%s remove (%.1fms)' % [event.payload[:column_family], event.duration]
11
+
12
+ message = " #{name} #{event.payload[:key]}"
13
+ message << " #{Array(event.payload[:attributes]).inspect}" if event.payload[:attributes]
14
+
15
+ debug message
16
+ end
17
+
18
+ def truncate(event)
19
+ name = '%s truncate (%.1fms)' % [event.payload[:column_family], event.duration]
20
+
21
+ debug " #{name} #{event.payload[:column_family]}"
22
+ end
23
+
24
+ def insert(event)
25
+ name = '%s insert (%.1fms)' % [event.payload[:column_family], event.duration]
26
+
27
+ debug " #{name} #{event.payload[:key]} #{event.payload[:attributes].inspect}"
28
+ end
29
+
30
+ def get_range(event)
31
+ name = '%s get_range (%.1fms)' % [event.payload[:column_family], event.duration]
32
+
33
+ debug " #{name} (#{event.payload[:count]}) '#{event.payload[:start]}' => '#{event.payload[:finish]}'"
34
+ end
35
+ end
36
+ end
37
+ DatastaxRails::LogSubscriber.attach_to :datastax_rails
@@ -0,0 +1,15 @@
1
+ module DatastaxRails
2
+ module Migrations
3
+ class Migration
4
+ attr_reader :version
5
+ def initialize(version, block)
6
+ @version = version
7
+ @block = block
8
+ end
9
+
10
+ def run(attrs)
11
+ @block.call(attrs)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,36 @@
1
+ module DatastaxRails
2
+ module Migrations
3
+ extend ActiveSupport::Concern
4
+ extend ActiveSupport::Autoload
5
+
6
+ included do
7
+ class_attribute :migrations
8
+ self.migrations = []
9
+
10
+ class_attribute :current_schema_version
11
+ self.current_schema_version = 0
12
+ end
13
+
14
+ autoload :Migration
15
+
16
+ class MigrationNotFoundError < StandardError
17
+ def initialize(record_version, migrations)
18
+ super("Cannot migrate a record from #{record_version.inspect}. Migrations exist for #{migrations.map(&:version)}")
19
+ end
20
+ end
21
+
22
+ def schema_version
23
+ Integer(@schema_version || self.class.current_schema_version)
24
+ end
25
+
26
+ module ClassMethods
27
+ def migrate(version, &blk)
28
+ migrations << Migration.new(version, blk)
29
+
30
+ if version > self.current_schema_version
31
+ self.current_schema_version = version
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,15 @@
1
+ require 'cassandra/mock'
2
+ module DatastaxRails
3
+ module Mocking
4
+ extend ActiveSupport::Concern
5
+ module ClassMethods
6
+ def use_mock!(really=true)
7
+ if really
8
+ self.connection_class = Cassandra::Mock
9
+ else
10
+ self.connection_class = Cassandra
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,133 @@
1
+ module DatastaxRails
2
+ module Persistence
3
+ extend ActiveSupport::Concern
4
+
5
+ module ClassMethods
6
+ def remove(*keys)
7
+ ActiveSupport::Notifications.instrument("remove.datastax_rails", :column_family => column_family, :key => key) do
8
+ cql.delete(keys).using(thrift_write_consistency).execute
9
+ end
10
+ end
11
+
12
+ def delete_all
13
+ ActiveSupport::Notifications.instrument("truncate.datastax_rails", :column_family => column_family) do
14
+ cql.truncate.execute
15
+ end
16
+ end
17
+
18
+ def create(attributes = {})
19
+ new(attributes).tap do |object|
20
+ object.save
21
+ end
22
+ end
23
+
24
+ def write(key, attributes, schema_version)
25
+ key.tap do |key|
26
+ attributes = encode_attributes(attributes, schema_version)
27
+ ActiveSupport::Notifications.instrument("insert.datastax_rails", :column_family => column_family, :key => key, :attributes => attributes) do
28
+ cql.update(key.to_s).columns(attributes).using(thrift_write_consistency).execute
29
+ end
30
+ end
31
+ end
32
+
33
+ def instantiate(key, attributes)
34
+ allocate.tap do |object|
35
+ object.instance_variable_set("@schema_version", attributes.delete('schema_version'))
36
+ object.instance_variable_set("@key", parse_key(key)) if key
37
+ object.instance_variable_set("@new_record", false)
38
+ object.instance_variable_set("@destroyed", false)
39
+ object.instance_variable_set("@attributes", typecast_attributes(object, attributes))
40
+ end
41
+ end
42
+
43
+ def encode_attributes(attributes, schema_version)
44
+ encoded = {"schema_version" => schema_version.to_s}
45
+ attributes.each do |column_name, value|
46
+ if value.nil?
47
+ encoded[column_name.to_s] = ""
48
+ else
49
+ encoded[column_name.to_s] = attribute_definitions[column_name.to_sym].coder.encode(value)
50
+ end
51
+ end
52
+ encoded
53
+ end
54
+
55
+ def typecast_attributes(object, attributes)
56
+ attributes = attributes.symbolize_keys
57
+ Hash[attribute_definitions.map { |k, attribute_definition| [k.to_s, attribute_definition.instantiate(object, attributes[k])] }]
58
+ end
59
+ end
60
+
61
+ def new_record?
62
+ @new_record
63
+ end
64
+
65
+ def destroyed?
66
+ @destroyed
67
+ end
68
+
69
+ def persisted?
70
+ !(new_record? || destroyed?)
71
+ end
72
+
73
+ def save(*)
74
+ begin
75
+ create_or_update
76
+ rescue DatastaxRails::RecordInvalid
77
+ false
78
+ end
79
+ end
80
+
81
+ def save!
82
+ create_or_update || raise(RecordNotSaved)
83
+ end
84
+
85
+ def destroy
86
+ self.class.remove(key)
87
+ @destroyed = true
88
+ freeze
89
+ end
90
+
91
+ def update_attribute(name, value)
92
+ name = name.to_s
93
+ send("#{name}=", value)
94
+ save(:validate => false)
95
+ end
96
+
97
+ def update_attributes(attributes)
98
+ self.attributes = attributes
99
+ save
100
+ end
101
+
102
+ def update_attributes!(attributes)
103
+ self.attributes = attributes
104
+ save!
105
+ end
106
+
107
+ def reload
108
+ @attributes.update(self.class.find(self.id).instance_variable_get('@attributes'))
109
+ end
110
+
111
+ private
112
+ def create_or_update
113
+ result = new_record? ? create : update
114
+ result != false
115
+ end
116
+
117
+ def create
118
+ @key ||= self.class.next_key(self)
119
+ write
120
+ @new_record = false
121
+ @key
122
+ end
123
+
124
+ def update
125
+ write
126
+ end
127
+
128
+ def write #:nodoc:
129
+ changed_attributes = changed.inject({}) { |h, n| h[n] = read_attribute(n); h }
130
+ self.class.write(key, changed_attributes, schema_version)
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,20 @@
1
+ require 'datastax_rails'
2
+ require 'rails'
3
+ module DatastaxRails
4
+ class Railtie < Rails::Railtie
5
+ initializer 'datastax_rails.init' do
6
+ ActiveSupport.on_load(:datastax_rails) do
7
+ end
8
+ config = YAML.load_file(Rails.root.join("config", "datastax.yml"))
9
+ DatastaxRails::Base.establish_connection(config[Rails.env].symbolize_keys)
10
+ end
11
+
12
+ rake_tasks do
13
+ load 'datastax_rails/tasks/ds.rake'
14
+ end
15
+
16
+ generators do
17
+ require 'datastax_rails/generators/migration_generator'
18
+ end
19
+ end
20
+ end