datastax_rails 2.0.12 → 2.0.15

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 (143) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +5 -5
  3. data/lib/blankslate.rb +8 -11
  4. data/lib/cql-rb_extensions.rb +5 -3
  5. data/lib/datastax_rails/associations/association.rb +93 -101
  6. data/lib/datastax_rails/associations/association_scope.rb +7 -7
  7. data/lib/datastax_rails/associations/belongs_to_association.rb +46 -48
  8. data/lib/datastax_rails/associations/builder/association.rb +32 -31
  9. data/lib/datastax_rails/associations/builder/belongs_to.rb +19 -20
  10. data/lib/datastax_rails/associations/builder/collection_association.rb +32 -32
  11. data/lib/datastax_rails/associations/builder/has_and_belongs_to_many.rb +21 -21
  12. data/lib/datastax_rails/associations/builder/has_many.rb +39 -40
  13. data/lib/datastax_rails/associations/builder/has_one.rb +30 -31
  14. data/lib/datastax_rails/associations/builder/singular_association.rb +31 -33
  15. data/lib/datastax_rails/associations/collection_association.rb +129 -135
  16. data/lib/datastax_rails/associations/collection_proxy.rb +21 -21
  17. data/lib/datastax_rails/associations/has_and_belongs_to_many_association.rb +26 -26
  18. data/lib/datastax_rails/associations/has_many_association.rb +38 -38
  19. data/lib/datastax_rails/associations/has_one_association.rb +31 -32
  20. data/lib/datastax_rails/associations/singular_association.rb +31 -30
  21. data/lib/datastax_rails/associations.rb +27 -24
  22. data/lib/datastax_rails/attribute_assignment.rb +17 -17
  23. data/lib/datastax_rails/attribute_methods/definition.rb +4 -4
  24. data/lib/datastax_rails/attribute_methods/dirty.rb +34 -33
  25. data/lib/datastax_rails/attribute_methods/primary_key.rb +3 -8
  26. data/lib/datastax_rails/attribute_methods/read.rb +10 -12
  27. data/lib/datastax_rails/attribute_methods/typecasting.rb +36 -35
  28. data/lib/datastax_rails/attribute_methods/write.rb +5 -6
  29. data/lib/datastax_rails/attribute_methods.rb +52 -56
  30. data/lib/datastax_rails/base.rb +122 -125
  31. data/lib/datastax_rails/callbacks.rb +15 -9
  32. data/lib/datastax_rails/cassandra_only_model.rb +6 -6
  33. data/lib/datastax_rails/collection.rb +5 -7
  34. data/lib/datastax_rails/column.rb +130 -118
  35. data/lib/datastax_rails/connection/statement_cache.rb +3 -3
  36. data/lib/datastax_rails/connection.rb +42 -33
  37. data/lib/datastax_rails/cql/alter_column_family.rb +19 -21
  38. data/lib/datastax_rails/cql/base.rb +8 -11
  39. data/lib/datastax_rails/cql/column_family.rb +11 -10
  40. data/lib/datastax_rails/cql/consistency.rb +2 -2
  41. data/lib/datastax_rails/cql/create_column_family.rb +15 -15
  42. data/lib/datastax_rails/cql/create_index.rb +5 -5
  43. data/lib/datastax_rails/cql/create_keyspace.rb +7 -7
  44. data/lib/datastax_rails/cql/delete.rb +16 -29
  45. data/lib/datastax_rails/cql/drop_column_family.rb +2 -2
  46. data/lib/datastax_rails/cql/drop_index.rb +2 -2
  47. data/lib/datastax_rails/cql/drop_keyspace.rb +2 -2
  48. data/lib/datastax_rails/cql/insert.rb +10 -16
  49. data/lib/datastax_rails/cql/select.rb +21 -33
  50. data/lib/datastax_rails/cql/truncate.rb +2 -2
  51. data/lib/datastax_rails/cql/update.rb +16 -24
  52. data/lib/datastax_rails/cql/use_keyspace.rb +2 -2
  53. data/lib/datastax_rails/cql.rb +2 -2
  54. data/lib/datastax_rails/dynamic_model.rb +32 -29
  55. data/lib/datastax_rails/errors.rb +6 -6
  56. data/lib/datastax_rails/grouped_collection.rb +3 -3
  57. data/lib/datastax_rails/inheritance.rb +9 -9
  58. data/lib/datastax_rails/payload_model.rb +24 -20
  59. data/lib/datastax_rails/persistence.rb +116 -110
  60. data/lib/datastax_rails/railtie.rb +7 -7
  61. data/lib/datastax_rails/reflection.rb +61 -59
  62. data/lib/datastax_rails/relation/batches.rb +12 -13
  63. data/lib/datastax_rails/relation/facet_methods.rb +44 -33
  64. data/lib/datastax_rails/relation/finder_methods.rb +95 -91
  65. data/lib/datastax_rails/relation/modification_methods.rb +5 -5
  66. data/lib/datastax_rails/relation/search_methods.rb +102 -102
  67. data/lib/datastax_rails/relation/spawn_methods.rb +25 -24
  68. data/lib/datastax_rails/relation/stats_methods.rb +9 -8
  69. data/lib/datastax_rails/relation.rb +165 -170
  70. data/lib/datastax_rails/rsolr_client_wrapper.rb +3 -3
  71. data/lib/datastax_rails/schema/cassandra.rb +44 -43
  72. data/lib/datastax_rails/schema/migrator.rb +52 -52
  73. data/lib/datastax_rails/schema/solr.rb +55 -47
  74. data/lib/datastax_rails/schema_cache.rb +1 -3
  75. data/lib/datastax_rails/scoping/default.rb +2 -3
  76. data/lib/datastax_rails/scoping/named.rb +3 -5
  77. data/lib/datastax_rails/scoping.rb +11 -12
  78. data/lib/datastax_rails/serialization.rb +34 -31
  79. data/lib/datastax_rails/serializers/xml_serializer.rb +178 -175
  80. data/lib/datastax_rails/timestamps.rb +4 -4
  81. data/lib/datastax_rails/types/dirty_collection.rb +57 -57
  82. data/lib/datastax_rails/types/dynamic_list.rb +1 -1
  83. data/lib/datastax_rails/types/dynamic_map.rb +5 -7
  84. data/lib/datastax_rails/types/dynamic_set.rb +2 -2
  85. data/lib/datastax_rails/util/solr_repair.rb +3 -3
  86. data/lib/datastax_rails/validations/associated.rb +8 -6
  87. data/lib/datastax_rails/validations/uniqueness.rb +8 -8
  88. data/lib/datastax_rails/validations.rb +9 -10
  89. data/lib/datastax_rails/version.rb +2 -1
  90. data/lib/datastax_rails/wide_storage_model.rb +6 -6
  91. data/lib/datastax_rails.rb +13 -9
  92. data/lib/schema_migration.rb +3 -3
  93. data/spec/datastax_rails/associations/belongs_to_association_spec.rb +2 -2
  94. data/spec/datastax_rails/associations/collection_association_spec.rb +14 -14
  95. data/spec/datastax_rails/associations/has_many_association_spec.rb +20 -20
  96. data/spec/datastax_rails/associations_spec.rb +11 -11
  97. data/spec/datastax_rails/attribute_methods_spec.rb +25 -25
  98. data/spec/datastax_rails/base_spec.rb +24 -24
  99. data/spec/datastax_rails/callbacks_spec.rb +21 -21
  100. data/spec/datastax_rails/column_spec.rb +133 -132
  101. data/spec/datastax_rails/connection/statement_cache_spec.rb +2 -2
  102. data/spec/datastax_rails/cql/base_spec.rb +4 -4
  103. data/spec/datastax_rails/cql/delete_spec.rb +19 -0
  104. data/spec/datastax_rails/cql/select_spec.rb +8 -8
  105. data/spec/datastax_rails/cql/update_spec.rb +8 -10
  106. data/spec/datastax_rails/dynamic_model_spec.rb +36 -22
  107. data/spec/datastax_rails/inheritance_spec.rb +11 -14
  108. data/spec/datastax_rails/persistence_spec.rb +73 -74
  109. data/spec/datastax_rails/relation/batches_spec.rb +13 -13
  110. data/spec/datastax_rails/relation/facet_methods_spec.rb +43 -35
  111. data/spec/datastax_rails/relation/finder_methods_spec.rb +77 -78
  112. data/spec/datastax_rails/relation/modification_methods_spec.rb +19 -19
  113. data/spec/datastax_rails/relation/search_methods_spec.rb +160 -160
  114. data/spec/datastax_rails/relation/spawn_methods_spec.rb +18 -18
  115. data/spec/datastax_rails/relation_spec.rb +119 -116
  116. data/spec/datastax_rails/schema/migrator_spec.rb +30 -30
  117. data/spec/datastax_rails/schema/solr_spec.rb +15 -15
  118. data/spec/datastax_rails/scoping/default_spec.rb +9 -9
  119. data/spec/datastax_rails/types/dynamic_list_spec.rb +12 -12
  120. data/spec/datastax_rails/types/dynamic_map_spec.rb +10 -10
  121. data/spec/datastax_rails/types/dynamic_set_spec.rb +22 -10
  122. data/spec/datastax_rails/validations/uniqueness_spec.rb +25 -25
  123. data/spec/datastax_rails/wide_storage_model_spec.rb +11 -0
  124. data/spec/datastax_rails_spec.rb +2 -2
  125. data/spec/dummy/config/application.rb +2 -3
  126. data/spec/dummy/config/boot.rb +1 -1
  127. data/spec/dummy/config/environments/development.rb +3 -3
  128. data/spec/dummy/config/environments/test.rb +1 -1
  129. data/spec/dummy/config/initializers/session_store.rb +1 -1
  130. data/spec/dummy/config/initializers/wrap_parameters.rb +1 -1
  131. data/spec/factories/audit_logs.rb +6 -0
  132. data/spec/factories/hobbies.rb +6 -0
  133. data/spec/factories/people.rb +5 -0
  134. data/spec/feature/dynamic_fields_spec.rb +4 -4
  135. data/spec/feature/overloaded_tables_spec.rb +11 -12
  136. data/spec/spec_helper.rb +17 -14
  137. data/spec/support/datastax_test_hook.rb +2 -2
  138. data/spec/support/default_consistency_shared_examples.rb +11 -11
  139. data/spec/support/models.rb +31 -32
  140. metadata +40 -6
  141. data/lib/datastax_rails/attribute_methods/before_type_cast.rb +0 -71
  142. data/lib/datastax_rails/log_subscriber.rb +0 -0
  143. data/spec/dummy/ks/migrate/20111117224534_models.rb +0 -20
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 98234dcb77c32791b630e27d4a9e4deb0be11068
4
- data.tar.gz: 0faf451aa7dfb597651ef4195d0849731ac43b7e
3
+ metadata.gz: eca5b1ed0b44ff67dffbe1c313ec3327b7011ac0
4
+ data.tar.gz: db1abc9e2a7c2577d7d20c8edf2492a81f88a2e2
5
5
  SHA512:
6
- metadata.gz: 6b0ca26bcaedfe88407c54badf618eb8968aa2cdbda4aac273c7d0422be89d79ce2b806af36d0bdebb41e8ad40a67a86c806065bec014ceb3d39ecf7a9ade7bf
7
- data.tar.gz: 9a502e20649c2e627bf4256e4e175860ef3004cd3fe6d418a0506c343ca2c8cb6eee8702a19aeef75d1cd10a7ed6b616f48e138bc933c24bbb002890cce95d78
6
+ metadata.gz: 919cf9003af455d8c2311b82801a8b3b2f33ef5fb004721c24128c6d76671207adc8ef2e6e4ea7961f14370bcd16846a53dc669956910757c7fc3b65f534a251
7
+ data.tar.gz: 2237e860f52576b248028d589a30773453783ccdf3e7c4bcb5bd688ff2b23064a7eed327805d06067931ecde65e0c7b7381a49df955a2c21a34f52eb8a668d1c
data/Rakefile CHANGED
@@ -22,15 +22,15 @@ RDoc::Task.new(:rdoc) do |rdoc|
22
22
  rdoc.rdoc_files.include('lib/**/*.rb')
23
23
  end
24
24
 
25
- APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
25
+ APP_RAKEFILE = File.expand_path('../spec/dummy/Rakefile', __FILE__)
26
26
  load 'rails/tasks/engine.rake'
27
27
 
28
28
  require 'rspec/core/rake_task'
29
29
  RSpec::Core::RakeTask.new(:spec) do |spec|
30
- #spec.rcov = true
31
- #spec.rcov_opts = %w{--rails --exclude osx\/objc,gems\/,spec\/,features\/,cassandra_object\/}
32
- spec.rspec_opts = File.read(File.expand_path("../spec/spec.opts", __FILE__)).split("\n")
30
+ # spec.rcov = true
31
+ # spec.rcov_opts = %w{--rails --exclude osx\/objc,gems\/,spec\/,features\/,cassandra_object\/}
32
+ spec.rspec_opts = File.read(File.expand_path('../spec/spec.opts', __FILE__)).split("\n")
33
33
  end
34
- task :default => :spec
34
+ task default: :spec
35
35
 
36
36
  Bundler::GemHelper.install_tasks
data/lib/blankslate.rb CHANGED
@@ -15,17 +15,14 @@
15
15
  # depend upon <tt>method_missing</tt> (e.g. dynamic proxies).
16
16
  class BlankSlate
17
17
  class << self
18
-
19
18
  # Hide the method named +name+ in the BlankSlate class. Don't
20
19
  # hide +instance_eval+ or any method beginning with "__".
21
20
  def hide(name)
22
21
  methods = instance_methods.map(&:to_sym)
23
- if methods.include?(name.to_sym) and
24
- name !~ /^(__|instance_eval|object_id)/
25
- @hidden_methods ||= {}
26
- @hidden_methods[name.to_sym] = instance_method(name)
27
- undef_method name
28
- end
22
+ return unless methods.include?(name.to_sym) && name !~ /^(__|instance_eval|object_id)/
23
+ @hidden_methods ||= {}
24
+ @hidden_methods[name.to_sym] = instance_method(name)
25
+ undef_method name
29
26
  end
30
27
 
31
28
  def find_hidden_method(name)
@@ -41,7 +38,7 @@ class BlankSlate
41
38
  define_method(name, hidden_method)
42
39
  end
43
40
  end
44
-
41
+
45
42
  instance_methods.each { |m| hide(m) }
46
43
  end
47
44
 
@@ -81,7 +78,7 @@ class Object
81
78
  result
82
79
  end
83
80
 
84
- def find_hidden_method(name)
81
+ def find_hidden_method(_name)
85
82
  nil
86
83
  end
87
84
  end
@@ -94,7 +91,7 @@ end
94
91
  # "feature" of Ruby prevents late includes into modules from being
95
92
  # exposed in the first place.
96
93
  class Module
97
- alias blankslate_original_append_features append_features
94
+ alias_method :blankslate_original_append_features, :append_features
98
95
  def append_features(mod)
99
96
  result = blankslate_original_append_features(mod)
100
97
  return result if mod != Object
@@ -103,4 +100,4 @@ class Module
103
100
  end
104
101
  result
105
102
  end
106
- end
103
+ end
@@ -1,3 +1,5 @@
1
+ # rubocop:disable Style/FileName
2
+
1
3
  # By default, cql-rb grabs a random connection for each request. This is great for
2
4
  # keeping load distributed across the cluster. Unfortunately, it plays havoc with
3
5
  # the Solr integration where we often need to ensure that we're talking to the
@@ -8,9 +10,9 @@ require 'cql/client/connection_manager'
8
10
 
9
11
  Cql::Client::ConnectionManager.class_eval do
10
12
  attr_reader :current_connection
11
-
13
+
12
14
  def random_connection
13
- raise NotConnectedError unless connected?
15
+ fail NotConnectedError unless connected?
14
16
  @lock.synchronize do
15
17
  @count ||= 0
16
18
  @count += 1
@@ -29,4 +31,4 @@ Cql::Client::SynchronousClient.class_eval do
29
31
  def current_connection
30
32
  async.instance_variable_get(:@connection_manager).current_connection
31
33
  end
32
- end
34
+ end
@@ -18,10 +18,11 @@ module DatastaxRails
18
18
  # HasManyAssociation
19
19
  # HasManyThroughAssociation + ThroughAssociation (Not implemented)
20
20
  class Association #:nodoc:
21
- attr_reader :owner, :target, :reflection
22
-
23
- delegate :options, :to => :reflection
24
-
21
+ attr_reader :owner, :target, :reflection, :loaded
22
+ alias_method :loaded?, :loaded
23
+
24
+ delegate :options, to: :reflection
25
+
25
26
  def initialize(owner, reflection)
26
27
  reflection.check_validity!
27
28
 
@@ -32,7 +33,7 @@ module DatastaxRails
32
33
  reset
33
34
  reset_scope
34
35
  end
35
-
36
+
36
37
  # Returns the name of the column family name of the related class:
37
38
  #
38
39
  # post.comments.aliased_column_family # => "comments"
@@ -40,13 +41,13 @@ module DatastaxRails
40
41
  def aliased_column_family
41
42
  reflection.klass.column_family
42
43
  end
43
-
44
+
44
45
  # Resets the \loaded flag to +false+ and sets the \target to +nil+.
45
46
  def reset
46
47
  @loaded = false
47
48
  @target = nil
48
49
  end
49
-
50
+
50
51
  # Reloads the \target and returns +self+ on success.
51
52
  def reload
52
53
  reset
@@ -54,18 +55,13 @@ module DatastaxRails
54
55
  load_target
55
56
  self unless target.nil?
56
57
  end
57
-
58
- # Has the \target been already \loaded?
59
- def loaded?
60
- @loaded
61
- end
62
-
58
+
63
59
  # Asserts the \target has been loaded setting the \loaded flag to +true+.
64
60
  def loaded!
65
61
  @loaded = true
66
62
  @stale_state = stale_state
67
63
  end
68
-
64
+
69
65
  # The target is stale if the target no longer points to the record(s) that the
70
66
  # relevant foreign_key(s) refers to. If stale, the association accessor method
71
67
  # on the owner will reload the target. It's up to subclasses to implement the
@@ -75,17 +71,17 @@ module DatastaxRails
75
71
  def stale_target?
76
72
  loaded? && @stale_state != stale_state
77
73
  end
78
-
74
+
79
75
  # Sets the target of this association to <tt>\target</tt>, and the \loaded flag to +true+.
80
76
  def target=(target)
81
77
  @target = target
82
78
  loaded!
83
79
  end
84
-
80
+
85
81
  def scoped
86
82
  target_scope.merge(association_scope)
87
83
  end
88
-
84
+
89
85
  # The scope for this association.
90
86
  #
91
87
  # Note that the association_scope is merged into the target_scope only when the
@@ -93,35 +89,32 @@ module DatastaxRails
93
89
  # by scope.scoping { ... } or with_scope { ... } etc, which affects the scope which
94
90
  # actually gets built.
95
91
  def association_scope
96
- if klass
97
- @association_scope ||= AssociationScope.new(self).scope
98
- end
92
+ @association_scope ||= AssociationScope.new(self).scope if klass
99
93
  end
100
-
94
+
101
95
  def reset_scope
102
96
  @association_scope = nil
103
97
  end
104
-
98
+
105
99
  # Set the inverse association, if possible
106
- def set_inverse_instance(record)
107
- if record && invertible_for?(record)
108
- inverse = record.association(inverse_reflection_for(record).name)
109
- inverse.target = owner
110
- end
100
+ def set_inverse_instance(record) # rubocop:disable Style/AccessorMethodName
101
+ return unless record && invertible_for?(record)
102
+ inverse = record.association(inverse_reflection_for(record).name)
103
+ inverse.target = owner
111
104
  end
112
-
105
+
113
106
  # This class of the target. belongs_to polymorphic overrides this to look at the
114
107
  # polymorphic_type field on the owner.
115
108
  def klass
116
109
  reflection.klass
117
110
  end
118
-
111
+
119
112
  # Can be overridden (i.e. in ThroughAssociation) to merge in other scopes (i.e. the
120
113
  # through association's scope)
121
114
  def target_scope
122
115
  klass.scoped
123
116
  end
124
-
117
+
125
118
  # Loads the \target if needed and returns it.
126
119
  #
127
120
  # This method is abstract in the sense that it relies on +find_target+,
@@ -133,9 +126,7 @@ module DatastaxRails
133
126
  # DatastaxRails::RecordNotFound is rescued within the method, and it is
134
127
  # not reraised. The proxy is \reset and +nil+ is the return value.
135
128
  def load_target
136
- if find_target?
137
- @target ||= find_target
138
- end
129
+ @target ||= find_target if find_target?
139
130
  loaded! unless loaded?
140
131
  target
141
132
  rescue DatastaxRails::RecordNotFound
@@ -143,79 +134,80 @@ module DatastaxRails
143
134
  end
144
135
 
145
136
  private
146
- def find_target?
147
- !loaded? && (!owner.new_record? || foreign_key_present?) && klass
148
- end
149
-
150
- def creation_attributes
151
- {}.tap do |attributes|
152
- if reflection.macro.in?([:has_one, :has_many]) && !options[:through]
153
- attributes[reflection.foreign_key] = owner.id
154
-
155
- # Note, polymorphic relationships are not implemented yet
156
- if reflection.options[:as]
157
- attributes[reflection.type] = owner.class.base_class.name
158
- end
137
+
138
+ def find_target?
139
+ !loaded? && (!owner.new_record? || foreign_key_present?) && klass
140
+ end
141
+
142
+ def creation_attributes
143
+ {}.tap do |attributes|
144
+ if reflection.macro.in?([:has_one, :has_many]) && !options[:through]
145
+ attributes[reflection.foreign_key] = owner.id
146
+
147
+ # Note, polymorphic relationships are not implemented yet
148
+ if reflection.options[:as]
149
+ attributes[reflection.type] = owner.class.base_class.name
159
150
  end
160
151
  end
161
152
  end
162
-
163
- # Sets the owner attributes on the given record
164
- def set_owner_attributes(record)
165
- creation_attributes.each { |key, value| record[key] = value }
166
- end
167
-
168
- # Should be true if there is a foreign key present on the owner which
169
- # references the target. This is used to determine whether we can load
170
- # the target if the owner is currently a new record (and therefore
171
- # without a key).
172
- #
173
- # Currently implemented by belongs_to (vanilla and polymorphic) and
174
- # has_one/has_many :through associations which go through a belongs_to
175
- def foreign_key_present?
176
- false
177
- end
178
-
179
- # Raises DatastaxRails::AssociationTypeMismatch unless +record+ is of
180
- # the kind of the class of the associated objects. Meant to be used as
181
- # a sanity check when you are about to assign an associated record.
182
- def raise_on_type_mismatch(record)
183
- unless record.is_a?(reflection.klass) || record.is_a?(reflection.class_name.constantize)
184
- message = "#{reflection.class_name}(##{reflection.klass.object_id}) expected, got #{record.class}(##{record.class.object_id})"
185
- raise DatastaxRails::AssociationTypeMismatch, message
186
- end
187
- end
188
-
189
- # Can be redefined by subclasses, notably polymorphic belongs_to
190
- # The record parameter is necessary to support polymorphic inverses as we must check for
191
- # the association in the specific class of the record.
192
- def inverse_reflection_for(record)
193
- reflection.inverse_of
194
- end
195
-
196
- # Is this association invertible? Can be redefined by subclasses.
197
- def invertible_for?(record)
198
- inverse_reflection_for(record)
199
- end
200
-
201
- # This should be implemented to return the values of the relevant key(s) on the owner,
202
- # so that when state_state is different from the value stored on the last find_target,
203
- # the target is stale.
204
- #
205
- # This is only relevant to certain associations, which is why it returns nil by default.
206
- def stale_state
207
- nil
208
- end
209
-
210
- def association_class
211
- @reflection.klass
212
- end
153
+ end
213
154
 
214
- def build_record(attributes, options)
215
- reflection.build_association(attributes, options) do |r|
216
- r.assign_attributes(create_scope.except(*r.changed))
217
- end
155
+ # Sets the owner attributes on the given record
156
+ def set_owner_attributes(record) # rubocop:disable Style/AccessorMethodName
157
+ creation_attributes.each { |key, value| record[key] = value }
158
+ end
159
+
160
+ # Should be true if there is a foreign key present on the owner which
161
+ # references the target. This is used to determine whether we can load
162
+ # the target if the owner is currently a new record (and therefore
163
+ # without a key).
164
+ #
165
+ # Currently implemented by belongs_to (vanilla and polymorphic) and
166
+ # has_one/has_many :through associations which go through a belongs_to
167
+ def foreign_key_present?
168
+ false
169
+ end
170
+
171
+ # Raises DatastaxRails::AssociationTypeMismatch unless +record+ is of
172
+ # the kind of the class of the associated objects. Meant to be used as
173
+ # a sanity check when you are about to assign an associated record.
174
+ def raise_on_type_mismatch(record)
175
+ return if record.is_a?(reflection.klass) || record.is_a?(reflection.class_name.constantize)
176
+ message = "#{reflection.class_name}(##{reflection.klass.object_id}) expected," \
177
+ " got #{record.class}(##{record.class.object_id})"
178
+ fail DatastaxRails::AssociationTypeMismatch, message
179
+ end
180
+
181
+ # Can be redefined by subclasses, notably polymorphic belongs_to
182
+ # The record parameter is necessary to support polymorphic inverses as we must check for
183
+ # the association in the specific class of the record.
184
+ def inverse_reflection_for(_record)
185
+ reflection.inverse_of
186
+ end
187
+
188
+ # Is this association invertible? Can be redefined by subclasses.
189
+ def invertible_for?(record)
190
+ inverse_reflection_for(record)
191
+ end
192
+
193
+ # This should be implemented to return the values of the relevant key(s) on the owner,
194
+ # so that when state_state is different from the value stored on the last find_target,
195
+ # the target is stale.
196
+ #
197
+ # This is only relevant to certain associations, which is why it returns nil by default.
198
+ def stale_state
199
+ nil
200
+ end
201
+
202
+ def association_class
203
+ @reflection.klass
204
+ end
205
+
206
+ def build_record(attributes, options)
207
+ reflection.build_association(attributes, options) do |r|
208
+ r.assign_attributes(create_scope.except(*r.changed))
218
209
  end
210
+ end
219
211
  end
220
212
  end
221
213
  end
@@ -2,18 +2,18 @@ module DatastaxRails
2
2
  module Associations
3
3
  class AssociationScope #:nodoc:
4
4
  attr_reader :association
5
-
6
- delegate :klass, :owner, :reflection, :to => :association
7
- delegate :chain, :options, :datastax_rails, :to => :reflection
8
-
5
+
6
+ delegate :klass, :owner, :reflection, to: :association
7
+ delegate :chain, :options, :datastax_rails, to: :reflection
8
+
9
9
  def initialize(association)
10
10
  @association = association
11
11
  end
12
-
12
+
13
13
  def scope
14
14
  scope = klass.unscoped
15
15
  scope = scope.extending(*Array.wrap(options[:extend]))
16
-
16
+
17
17
  if reflection.source_macro == :belongs_to
18
18
  scope.where('id' => owner.send(reflection.foreign_key))
19
19
  else
@@ -22,4 +22,4 @@ module DatastaxRails
22
22
  end
23
23
  end
24
24
  end
25
- end
25
+ end
@@ -1,65 +1,63 @@
1
1
  module DatastaxRails
2
2
  module Associations
3
3
  class BelongsToAssociation < SingularAssociation #:nodoc:
4
+ attr_reader :updated
5
+ alias_method :updated?, :updated
4
6
  def replace(record)
5
7
  raise_on_type_mismatch(record) if record
6
-
8
+
7
9
  replace_keys(record)
8
10
  set_inverse_instance(record)
9
-
11
+
10
12
  @updated = true if record
11
-
13
+
12
14
  self.target = record
13
15
  end
14
-
15
- def updated?
16
- @updated
17
- end
18
-
16
+
19
17
  private
20
-
21
- def find_target?
22
- !loaded? && foreign_key_present? && klass
23
- end
24
-
25
- # Checks whether record is different to the current target, without loading it
26
- def different_target?(record)
27
- record.nil? && owner[reflection.foreign_key] ||
28
- record && record.id != owner[reflection.foreign_key]
29
- end
30
-
31
- def replace_keys(record)
32
- owner.loaded_attributes[reflection.foreign_key] = true
33
- owner.send("#{reflection.foreign_key}_will_change!")
34
- if record
35
- owner[reflection.foreign_key] = record.id
36
- else
37
- owner[reflection.foreign_key] = nil
38
- end
39
- end
40
-
41
- def foreign_key_present?
42
- owner[reflection.foreign_key]
43
- end
44
-
45
- # NOTE - for now, we're only supporting inverse setting from belongs_to back onto
46
- # has_one associations.
47
- def invertible_for?(record)
48
- inverse = inverse_reflection_for(record)
49
- inverse && inverse.macro == :has_one
50
- end
51
18
 
52
- def target_id
53
- if options[:primary_key]
54
- owner.send(reflection.name).try(:id)
55
- else
56
- owner[reflection.foreign_key]
57
- end
19
+ def find_target?
20
+ !loaded? && foreign_key_present? && klass
21
+ end
22
+
23
+ # Checks whether record is different to the current target, without loading it
24
+ def different_target?(record)
25
+ record.nil? && owner[reflection.foreign_key] ||
26
+ record && record.id != owner[reflection.foreign_key]
27
+ end
28
+
29
+ def replace_keys(record)
30
+ owner.loaded_attributes[reflection.foreign_key] = true
31
+ owner.send("#{reflection.foreign_key}_will_change!")
32
+ if record
33
+ owner[reflection.foreign_key] = record.id
34
+ else
35
+ owner[reflection.foreign_key] = nil
58
36
  end
37
+ end
38
+
39
+ def foreign_key_present?
40
+ owner[reflection.foreign_key]
41
+ end
59
42
 
60
- def stale_state
61
- owner[reflection.foreign_key].to_s
43
+ # NOTE - for now, we're only supporting inverse setting from belongs_to back onto
44
+ # has_one associations.
45
+ def invertible_for?(record)
46
+ inverse = inverse_reflection_for(record)
47
+ inverse && inverse.macro == :has_one
48
+ end
49
+
50
+ def target_id
51
+ if options[:primary_key]
52
+ owner.send(reflection.name).try(:id)
53
+ else
54
+ owner[reflection.foreign_key]
62
55
  end
56
+ end
57
+
58
+ def stale_state
59
+ owner[reflection.foreign_key].to_s
60
+ end
63
61
  end
64
62
  end
65
- end
63
+ end