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.
- checksums.yaml +4 -4
- data/Rakefile +5 -5
- data/lib/blankslate.rb +8 -11
- data/lib/cql-rb_extensions.rb +5 -3
- data/lib/datastax_rails/associations/association.rb +93 -101
- data/lib/datastax_rails/associations/association_scope.rb +7 -7
- data/lib/datastax_rails/associations/belongs_to_association.rb +46 -48
- data/lib/datastax_rails/associations/builder/association.rb +32 -31
- data/lib/datastax_rails/associations/builder/belongs_to.rb +19 -20
- data/lib/datastax_rails/associations/builder/collection_association.rb +32 -32
- data/lib/datastax_rails/associations/builder/has_and_belongs_to_many.rb +21 -21
- data/lib/datastax_rails/associations/builder/has_many.rb +39 -40
- data/lib/datastax_rails/associations/builder/has_one.rb +30 -31
- data/lib/datastax_rails/associations/builder/singular_association.rb +31 -33
- data/lib/datastax_rails/associations/collection_association.rb +129 -135
- data/lib/datastax_rails/associations/collection_proxy.rb +21 -21
- data/lib/datastax_rails/associations/has_and_belongs_to_many_association.rb +26 -26
- data/lib/datastax_rails/associations/has_many_association.rb +38 -38
- data/lib/datastax_rails/associations/has_one_association.rb +31 -32
- data/lib/datastax_rails/associations/singular_association.rb +31 -30
- data/lib/datastax_rails/associations.rb +27 -24
- data/lib/datastax_rails/attribute_assignment.rb +17 -17
- data/lib/datastax_rails/attribute_methods/definition.rb +4 -4
- data/lib/datastax_rails/attribute_methods/dirty.rb +34 -33
- data/lib/datastax_rails/attribute_methods/primary_key.rb +3 -8
- data/lib/datastax_rails/attribute_methods/read.rb +10 -12
- data/lib/datastax_rails/attribute_methods/typecasting.rb +36 -35
- data/lib/datastax_rails/attribute_methods/write.rb +5 -6
- data/lib/datastax_rails/attribute_methods.rb +52 -56
- data/lib/datastax_rails/base.rb +122 -125
- data/lib/datastax_rails/callbacks.rb +15 -9
- data/lib/datastax_rails/cassandra_only_model.rb +6 -6
- data/lib/datastax_rails/collection.rb +5 -7
- data/lib/datastax_rails/column.rb +130 -118
- data/lib/datastax_rails/connection/statement_cache.rb +3 -3
- data/lib/datastax_rails/connection.rb +42 -33
- data/lib/datastax_rails/cql/alter_column_family.rb +19 -21
- data/lib/datastax_rails/cql/base.rb +8 -11
- data/lib/datastax_rails/cql/column_family.rb +11 -10
- data/lib/datastax_rails/cql/consistency.rb +2 -2
- data/lib/datastax_rails/cql/create_column_family.rb +15 -15
- data/lib/datastax_rails/cql/create_index.rb +5 -5
- data/lib/datastax_rails/cql/create_keyspace.rb +7 -7
- data/lib/datastax_rails/cql/delete.rb +16 -29
- data/lib/datastax_rails/cql/drop_column_family.rb +2 -2
- data/lib/datastax_rails/cql/drop_index.rb +2 -2
- data/lib/datastax_rails/cql/drop_keyspace.rb +2 -2
- data/lib/datastax_rails/cql/insert.rb +10 -16
- data/lib/datastax_rails/cql/select.rb +21 -33
- data/lib/datastax_rails/cql/truncate.rb +2 -2
- data/lib/datastax_rails/cql/update.rb +16 -24
- data/lib/datastax_rails/cql/use_keyspace.rb +2 -2
- data/lib/datastax_rails/cql.rb +2 -2
- data/lib/datastax_rails/dynamic_model.rb +32 -29
- data/lib/datastax_rails/errors.rb +6 -6
- data/lib/datastax_rails/grouped_collection.rb +3 -3
- data/lib/datastax_rails/inheritance.rb +9 -9
- data/lib/datastax_rails/payload_model.rb +24 -20
- data/lib/datastax_rails/persistence.rb +116 -110
- data/lib/datastax_rails/railtie.rb +7 -7
- data/lib/datastax_rails/reflection.rb +61 -59
- data/lib/datastax_rails/relation/batches.rb +12 -13
- data/lib/datastax_rails/relation/facet_methods.rb +44 -33
- data/lib/datastax_rails/relation/finder_methods.rb +95 -91
- data/lib/datastax_rails/relation/modification_methods.rb +5 -5
- data/lib/datastax_rails/relation/search_methods.rb +102 -102
- data/lib/datastax_rails/relation/spawn_methods.rb +25 -24
- data/lib/datastax_rails/relation/stats_methods.rb +9 -8
- data/lib/datastax_rails/relation.rb +165 -170
- data/lib/datastax_rails/rsolr_client_wrapper.rb +3 -3
- data/lib/datastax_rails/schema/cassandra.rb +44 -43
- data/lib/datastax_rails/schema/migrator.rb +52 -52
- data/lib/datastax_rails/schema/solr.rb +55 -47
- data/lib/datastax_rails/schema_cache.rb +1 -3
- data/lib/datastax_rails/scoping/default.rb +2 -3
- data/lib/datastax_rails/scoping/named.rb +3 -5
- data/lib/datastax_rails/scoping.rb +11 -12
- data/lib/datastax_rails/serialization.rb +34 -31
- data/lib/datastax_rails/serializers/xml_serializer.rb +178 -175
- data/lib/datastax_rails/timestamps.rb +4 -4
- data/lib/datastax_rails/types/dirty_collection.rb +57 -57
- data/lib/datastax_rails/types/dynamic_list.rb +1 -1
- data/lib/datastax_rails/types/dynamic_map.rb +5 -7
- data/lib/datastax_rails/types/dynamic_set.rb +2 -2
- data/lib/datastax_rails/util/solr_repair.rb +3 -3
- data/lib/datastax_rails/validations/associated.rb +8 -6
- data/lib/datastax_rails/validations/uniqueness.rb +8 -8
- data/lib/datastax_rails/validations.rb +9 -10
- data/lib/datastax_rails/version.rb +2 -1
- data/lib/datastax_rails/wide_storage_model.rb +6 -6
- data/lib/datastax_rails.rb +13 -9
- data/lib/schema_migration.rb +3 -3
- data/spec/datastax_rails/associations/belongs_to_association_spec.rb +2 -2
- data/spec/datastax_rails/associations/collection_association_spec.rb +14 -14
- data/spec/datastax_rails/associations/has_many_association_spec.rb +20 -20
- data/spec/datastax_rails/associations_spec.rb +11 -11
- data/spec/datastax_rails/attribute_methods_spec.rb +25 -25
- data/spec/datastax_rails/base_spec.rb +24 -24
- data/spec/datastax_rails/callbacks_spec.rb +21 -21
- data/spec/datastax_rails/column_spec.rb +133 -132
- data/spec/datastax_rails/connection/statement_cache_spec.rb +2 -2
- data/spec/datastax_rails/cql/base_spec.rb +4 -4
- data/spec/datastax_rails/cql/delete_spec.rb +19 -0
- data/spec/datastax_rails/cql/select_spec.rb +8 -8
- data/spec/datastax_rails/cql/update_spec.rb +8 -10
- data/spec/datastax_rails/dynamic_model_spec.rb +36 -22
- data/spec/datastax_rails/inheritance_spec.rb +11 -14
- data/spec/datastax_rails/persistence_spec.rb +73 -74
- data/spec/datastax_rails/relation/batches_spec.rb +13 -13
- data/spec/datastax_rails/relation/facet_methods_spec.rb +43 -35
- data/spec/datastax_rails/relation/finder_methods_spec.rb +77 -78
- data/spec/datastax_rails/relation/modification_methods_spec.rb +19 -19
- data/spec/datastax_rails/relation/search_methods_spec.rb +160 -160
- data/spec/datastax_rails/relation/spawn_methods_spec.rb +18 -18
- data/spec/datastax_rails/relation_spec.rb +119 -116
- data/spec/datastax_rails/schema/migrator_spec.rb +30 -30
- data/spec/datastax_rails/schema/solr_spec.rb +15 -15
- data/spec/datastax_rails/scoping/default_spec.rb +9 -9
- data/spec/datastax_rails/types/dynamic_list_spec.rb +12 -12
- data/spec/datastax_rails/types/dynamic_map_spec.rb +10 -10
- data/spec/datastax_rails/types/dynamic_set_spec.rb +22 -10
- data/spec/datastax_rails/validations/uniqueness_spec.rb +25 -25
- data/spec/datastax_rails/wide_storage_model_spec.rb +11 -0
- data/spec/datastax_rails_spec.rb +2 -2
- data/spec/dummy/config/application.rb +2 -3
- data/spec/dummy/config/boot.rb +1 -1
- data/spec/dummy/config/environments/development.rb +3 -3
- data/spec/dummy/config/environments/test.rb +1 -1
- data/spec/dummy/config/initializers/session_store.rb +1 -1
- data/spec/dummy/config/initializers/wrap_parameters.rb +1 -1
- data/spec/factories/audit_logs.rb +6 -0
- data/spec/factories/hobbies.rb +6 -0
- data/spec/factories/people.rb +5 -0
- data/spec/feature/dynamic_fields_spec.rb +4 -4
- data/spec/feature/overloaded_tables_spec.rb +11 -12
- data/spec/spec_helper.rb +17 -14
- data/spec/support/datastax_test_hook.rb +2 -2
- data/spec/support/default_consistency_shared_examples.rb +11 -11
- data/spec/support/models.rb +31 -32
- metadata +40 -6
- data/lib/datastax_rails/attribute_methods/before_type_cast.rb +0 -71
- data/lib/datastax_rails/log_subscriber.rb +0 -0
- data/spec/dummy/ks/migrate/20111117224534_models.rb +0 -20
@@ -4,8 +4,8 @@ module DatastaxRails
|
|
4
4
|
#
|
5
5
|
# * Find by id - This can either be a specific id (1), a list of ids (1, 5, 6), or an array of ids ([5, 6, 10]).
|
6
6
|
# If no record can be found for all of the listed ids, then RecordNotFound will be raised.
|
7
|
-
# * Find first - This will return the first record matched by the options used. These options can either be
|
8
|
-
# conditions or merely an order. If no record can be matched, +nil+ is returned. Use
|
7
|
+
# * Find first - This will return the first record matched by the options used. These options can either be
|
8
|
+
# specific conditions or merely an order. If no record can be matched, +nil+ is returned. Use
|
9
9
|
# <tt>Model.find(:first, *args)</tt> or its shortcut <tt>Model.first(*args)</tt>.
|
10
10
|
# * Find last - This will return the last record matched by the options used. These options can either be specific
|
11
11
|
# conditions or merely an order. If no record can be matched, +nil+ is returned. Use
|
@@ -20,7 +20,6 @@ module DatastaxRails
|
|
20
20
|
#
|
21
21
|
# * <tt>:conditions</tt> - See conditions in the intro.
|
22
22
|
# * <tt>:order</tt> - An SQL fragment like "created_at DESC, name".
|
23
|
-
# * <tt>:group</tt> - An attribute name by which the result should be grouped. Uses the <tt>GROUP BY</tt> SQL-clause.
|
24
23
|
# * <tt>:limit</tt> - An integer determining the limit on the number of rows that should be returned.
|
25
24
|
# * <tt>:offset</tt> - An integer determining the offset from where the rows should be fetched. So at 5,
|
26
25
|
# it would skip rows 0 through 4.
|
@@ -71,7 +70,7 @@ module DatastaxRails
|
|
71
70
|
end
|
72
71
|
end
|
73
72
|
end
|
74
|
-
|
73
|
+
|
75
74
|
# Finds the first record matching the specified conditions. There
|
76
75
|
# is no implied ordering so if order matters, you should specify it
|
77
76
|
# yourself.
|
@@ -96,7 +95,7 @@ module DatastaxRails
|
|
96
95
|
# same arguments to this method as you can to <tt>find(:first)</tt>.
|
97
96
|
def first(*args)
|
98
97
|
if args.any?
|
99
|
-
if args.first.
|
98
|
+
if args.first.is_a?(Integer) || (loaded? && !args.first.is_a?(Hash))
|
100
99
|
limit(*args).to_a
|
101
100
|
else
|
102
101
|
apply_finder_options(args.first).first
|
@@ -105,20 +104,20 @@ module DatastaxRails
|
|
105
104
|
find_first
|
106
105
|
end
|
107
106
|
end
|
108
|
-
|
107
|
+
|
109
108
|
# Same as +first+ but raises <tt>DatastaxRails::RecordNotFound</tt> if no record
|
110
109
|
# is found. Note that <tt>first!</tt> accepts no arguments.
|
111
110
|
def first!
|
112
|
-
first
|
111
|
+
first || fail(RecordNotFound)
|
113
112
|
end
|
114
|
-
|
113
|
+
|
115
114
|
# A convenience wrapper for <tt>find(:last, *args)</tt>. You can pass in all the
|
116
115
|
# same arguments to this method as you can to <tt>find(:last)</tt>.
|
117
116
|
def last(*args)
|
118
117
|
if args.any?
|
119
|
-
if args.first.
|
118
|
+
if args.first.is_a?(Integer) || (loaded? && !args.first.is_a?(Hash))
|
120
119
|
if order_values.empty? && reorder_value.nil?
|
121
|
-
order(:
|
120
|
+
order(id: :desc).limit(*args).reverse
|
122
121
|
else
|
123
122
|
to_a.last(*args)
|
124
123
|
end
|
@@ -133,101 +132,106 @@ module DatastaxRails
|
|
133
132
|
# Same as +last+ but raises <tt>DatastaxRails::RecordNotFound</tt> if no record
|
134
133
|
# is found. Note that <tt>last!</tt> accepts no arguments.
|
135
134
|
def last!
|
136
|
-
last
|
135
|
+
last || fail(RecordNotFound)
|
137
136
|
end
|
138
|
-
|
137
|
+
|
139
138
|
protected
|
140
|
-
def find_by_attributes(match, attributes, *args) #:nodoc:
|
141
|
-
|
142
|
-
conditions = Hash[attributes.map {|a| [a, args[attributes.index(a)]]}]
|
143
|
-
result = self.send(match.finder, conditions)
|
144
139
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
140
|
+
def find_by_attributes(match, attributes, *args) #:nodoc:
|
141
|
+
conditions = Hash[attributes.map { |a| [a, args[attributes.index(a)]] }]
|
142
|
+
result = send(match.finder, conditions)
|
143
|
+
|
144
|
+
if match.blank? && result.blank?
|
145
|
+
fail RecordNotFound, "Couldn't find #{klass.name} with #{conditions.to_a.map { |p| p.join('=') }.join(', ')}"
|
146
|
+
else
|
147
|
+
yield(result) if block_given?
|
148
|
+
result
|
151
149
|
end
|
152
|
-
|
150
|
+
end
|
151
|
+
|
153
152
|
private
|
154
153
|
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
else
|
161
|
-
escaped[k] = v
|
162
|
-
end
|
163
|
-
end
|
164
|
-
escaped
|
165
|
-
end
|
166
|
-
|
167
|
-
def find_with_ids(*ids)
|
168
|
-
return to_a.find { |*block_args| yield(*block_args) } if block_given?
|
169
|
-
|
170
|
-
expects_array = ids.first.kind_of?(Array)
|
171
|
-
return ids.first if expects_array && ids.first.empty?
|
172
|
-
|
173
|
-
ids = ids.flatten.compact.uniq
|
174
|
-
|
175
|
-
case ids.size
|
176
|
-
when 0
|
177
|
-
raise RecordNotFound, "Couldn't find #{@klass.name} without an ID"
|
178
|
-
when 1
|
179
|
-
result = find_one(ids.first)
|
180
|
-
expects_array ? [ result ] : result
|
154
|
+
def escape_attributes(conditions)
|
155
|
+
escaped = {}
|
156
|
+
conditions.each do |k, v|
|
157
|
+
if v.is_a?(String)
|
158
|
+
escaped[k] = v.gsub(/(\W)/, '\\\\\1')
|
181
159
|
else
|
182
|
-
|
160
|
+
escaped[k] = v
|
183
161
|
end
|
184
162
|
end
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
163
|
+
escaped
|
164
|
+
end
|
165
|
+
|
166
|
+
def find_with_ids(*ids)
|
167
|
+
return to_a.find { |*block_args| yield(*block_args) } if block_given?
|
168
|
+
|
169
|
+
expects_array = ids.first.is_a?(Array)
|
170
|
+
return ids.first if expects_array && ids.first.empty?
|
171
|
+
|
172
|
+
ids = ids.flatten.compact.uniq
|
173
|
+
|
174
|
+
case ids.size
|
175
|
+
when 0
|
176
|
+
fail RecordNotFound, "Couldn't find #{@klass.name} without an ID"
|
177
|
+
when 1
|
178
|
+
result = find_one(ids.first)
|
179
|
+
expects_array ? [result] : result
|
180
|
+
else
|
181
|
+
find_some(ids)
|
190
182
|
end
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
expected_size = ids.size - @offset_value
|
206
|
-
end
|
207
|
-
|
208
|
-
if result.size == expected_size
|
209
|
-
result
|
210
|
-
else
|
211
|
-
error = "Couldn't find all #{@klass.name.pluralize} with IDs "
|
212
|
-
error << "(#{ids.join(", ")}) (found #{result.size} results, but was looking for #{expected_size})"
|
213
|
-
raise RecordNotFound, error
|
214
|
-
end
|
183
|
+
end
|
184
|
+
|
185
|
+
def find_one(id)
|
186
|
+
key = @klass.attribute_definitions[@klass.primary_key].type_cast(id)
|
187
|
+
key || fail(RecordNotFound, "Couldn't find #{@klass.name} with an invalid ID=#{id}")
|
188
|
+
|
189
|
+
with_cassandra.where(@klass.primary_key => key).first ||
|
190
|
+
fail(RecordNotFound, "Couldn't find #{@klass.name} with ID=#{id}")
|
191
|
+
end
|
192
|
+
|
193
|
+
def find_some(ids)
|
194
|
+
keys = ids.map do |id|
|
195
|
+
@klass.attribute_definitions[@klass.primary_key].type_cast(id) ||
|
196
|
+
fail(RecordNotFound, "Couldn't find #{@klass.name} with an invalid ID=#{id}")
|
215
197
|
end
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
198
|
+
result = with_cassandra.where(@klass.primary_key => keys).all
|
199
|
+
|
200
|
+
expected_size =
|
201
|
+
if @limit_value && ids.size > @limit_value
|
202
|
+
@limit_value
|
220
203
|
else
|
221
|
-
|
204
|
+
ids.size
|
222
205
|
end
|
206
|
+
|
207
|
+
# 11 ids with limit 3, offset 9 should give 2 results.
|
208
|
+
if @offset_value && (ids.size - @offset_value < expected_size)
|
209
|
+
expected_size = ids.size - @offset_value
|
223
210
|
end
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
211
|
+
|
212
|
+
if result.size == expected_size
|
213
|
+
result
|
214
|
+
else
|
215
|
+
error = "Couldn't find all #{@klass.name.pluralize} with IDs "
|
216
|
+
error << "(#{ids.join(', ')}) (found #{result.size} results, but was looking for #{expected_size})"
|
217
|
+
fail RecordNotFound, error
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
def find_first
|
222
|
+
if loaded?
|
223
|
+
@results.first
|
224
|
+
else
|
225
|
+
@first ||= limit(1).to_a[0]
|
231
226
|
end
|
227
|
+
end
|
228
|
+
|
229
|
+
def find_last
|
230
|
+
if loaded?
|
231
|
+
@results.last
|
232
|
+
else
|
233
|
+
@last ||= reverse_order.limit(1).to_a[0]
|
234
|
+
end
|
235
|
+
end
|
232
236
|
end
|
233
237
|
end
|
@@ -32,14 +32,14 @@ module DatastaxRails
|
|
32
32
|
if conditions
|
33
33
|
ret = where(conditions).destroy_all
|
34
34
|
else
|
35
|
-
ret = to_a.each {|object| object.destroy }
|
35
|
+
ret = to_a.each { |object| object.destroy }
|
36
36
|
end
|
37
37
|
reset
|
38
38
|
ret
|
39
39
|
end
|
40
40
|
# TODO: Find a way to delete from both without instantiating
|
41
|
-
|
42
|
-
|
41
|
+
alias_method :delete_all, :destroy_all
|
42
|
+
|
43
43
|
# Destroy an object (or multiple objects) that has the given id, the object is instantiated first,
|
44
44
|
# therefore all callbacks and filters are fired off before the object is deleted. This method is
|
45
45
|
# in-efficient since it actually has to instantiate the object just to delte it but allows cleanup
|
@@ -75,6 +75,6 @@ module DatastaxRails
|
|
75
75
|
reset
|
76
76
|
ret
|
77
77
|
end
|
78
|
-
|
78
|
+
alias_method :delete, :destroy
|
79
79
|
end
|
80
|
-
end
|
80
|
+
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
module DatastaxRails
|
2
2
|
module SearchMethods
|
3
|
-
|
4
3
|
# By default, Cassandra will throw an error if you try to set a where condition
|
5
4
|
# on either a column with no index or on more than one column that isn't part
|
6
5
|
# of the primary key. If you are confident that the number of records that need
|
@@ -19,19 +18,19 @@ module DatastaxRails
|
|
19
18
|
r.allow_filtering_value = true
|
20
19
|
end
|
21
20
|
end
|
22
|
-
|
21
|
+
|
23
22
|
# The default consistency level for DSR is QUORUM when searching by ID.
|
24
23
|
# For all searches using SOLR, the default consistency is ONE. Use this
|
25
24
|
# to override it in either case.
|
26
|
-
#
|
25
|
+
#
|
27
26
|
# Model.consistency(:local_quorum).find("12345")
|
28
27
|
#
|
29
28
|
# Note that Solr searches don't allow you to specify the consistency level.
|
30
29
|
# DSR sort of gets around this by taking the search results and then going
|
31
30
|
# to Cassandra to retrieve the objects by ID using the consistency you specified.
|
32
|
-
# However, it is possible that you might not get all of the records you are
|
33
|
-
# expecting if the SOLR node you were talking to hasn't been updated yet with
|
34
|
-
# the results. In practice, this should not happen for records that were created
|
31
|
+
# However, it is possible that you might not get all of the records you are
|
32
|
+
# expecting if the SOLR node you were talking to hasn't been updated yet with
|
33
|
+
# the results. In practice, this should not happen for records that were created
|
35
34
|
# over your connection, but it is possible for other connections to create records
|
36
35
|
# that you can't see yet.
|
37
36
|
#
|
@@ -48,14 +47,14 @@ module DatastaxRails
|
|
48
47
|
def consistency(level)
|
49
48
|
level = level.to_s.upcase
|
50
49
|
unless self.valid_consistency?(level)
|
51
|
-
|
50
|
+
fail ArgumentError, "'#{level}' is not a valid Cassandra consistency level"
|
52
51
|
end
|
53
|
-
|
52
|
+
|
54
53
|
clone.tap do |r|
|
55
54
|
r.consistency_value = level
|
56
55
|
end
|
57
|
-
end
|
58
|
-
|
56
|
+
end
|
57
|
+
|
59
58
|
# Normally special characters (other than wild cards) are escaped before the search
|
60
59
|
# is submitted. If you want to handle escaping yourself because you need to use
|
61
60
|
# those special characters, then just include this in your chain.
|
@@ -71,8 +70,8 @@ module DatastaxRails
|
|
71
70
|
r.escape_value = false
|
72
71
|
end
|
73
72
|
end
|
74
|
-
|
75
|
-
# Used to extend a scope with additional methods, either through
|
73
|
+
|
74
|
+
# Used to extend a scope with additional methods, either through
|
76
75
|
# a module or a block provided
|
77
76
|
#
|
78
77
|
# The object returned is a relation which can be further extended
|
@@ -88,7 +87,7 @@ module DatastaxRails
|
|
88
87
|
r.send(:apply_modules, modules.flatten)
|
89
88
|
end
|
90
89
|
end
|
91
|
-
|
90
|
+
|
92
91
|
# Limit a single page to +value+ records
|
93
92
|
#
|
94
93
|
# Model.limit(1)
|
@@ -112,8 +111,8 @@ module DatastaxRails
|
|
112
111
|
r.per_page_value = value.to_i
|
113
112
|
end
|
114
113
|
end
|
115
|
-
|
116
|
-
|
114
|
+
alias_method :per_page, :limit
|
115
|
+
|
117
116
|
# Sets the page number to retrieve
|
118
117
|
#
|
119
118
|
# Model.page(2)
|
@@ -125,7 +124,7 @@ module DatastaxRails
|
|
125
124
|
r.page_value = value.to_i
|
126
125
|
end
|
127
126
|
end
|
128
|
-
|
127
|
+
|
129
128
|
# WillPaginate compatible method for paginating
|
130
129
|
#
|
131
130
|
# Model.paginate(page: 2, per_page: 10)
|
@@ -135,13 +134,13 @@ module DatastaxRails
|
|
135
134
|
# @option options [String, Fixnum] :per_page the number of records to include on a page
|
136
135
|
# @return [DatastaxRails::Relation] a new Relation object
|
137
136
|
def paginate(options = {})
|
138
|
-
options = options.reverse_merge(
|
137
|
+
options = options.reverse_merge(page: 1, per_page: 30)
|
139
138
|
clone.tap do |r|
|
140
139
|
r.page_value = options[:page]
|
141
140
|
r.per_page_value = options[:per_page]
|
142
141
|
end
|
143
142
|
end
|
144
|
-
|
143
|
+
|
145
144
|
# Group results by a given attribute only returning the top results
|
146
145
|
# for each group. In Lucene, this is often referred to as Field Collapsing.
|
147
146
|
#
|
@@ -168,16 +167,16 @@ module DatastaxRails
|
|
168
167
|
# @return [DatastaxRails::Relation] a new Relation object
|
169
168
|
def group(attribute)
|
170
169
|
return self if attribute.blank?
|
171
|
-
|
170
|
+
|
172
171
|
clone.tap do |r|
|
173
172
|
r.group_value = attribute
|
174
173
|
end
|
175
174
|
end
|
176
|
-
|
175
|
+
|
177
176
|
# Orders the result set by a particular attribute. Note that text fields
|
178
177
|
# may not be used for ordering as they are tokenized. Valid candidates
|
179
178
|
# are fields of type +string+, +integer+, +long+, +float+, +double+, and
|
180
|
-
# +time+. In addition, the symbol +:score+ can be used to sort on the
|
179
|
+
# +time+. In addition, the symbol +:score+ can be used to sort on the
|
181
180
|
# relevance rating returned by Solr. The default direction is ascending
|
182
181
|
# but may be reversed by passing a hash where the field is the key and
|
183
182
|
# the value is :desc
|
@@ -186,7 +185,7 @@ module DatastaxRails
|
|
186
185
|
# Model.order(name: :desc)
|
187
186
|
#
|
188
187
|
# WARNING: If this call is combined with #with_cassandra, you can only
|
189
|
-
# order on the cluster_by column. If this doesn't mean anything to you,
|
188
|
+
# order on the cluster_by column. If this doesn't mean anything to you,
|
190
189
|
# then you probably don't want to use these together.
|
191
190
|
#
|
192
191
|
# @param attribute [Symbol, String, Hash] the attribute to sort by and optionally the direction to sort in
|
@@ -195,10 +194,10 @@ module DatastaxRails
|
|
195
194
|
return self if attribute.blank?
|
196
195
|
|
197
196
|
clone.tap do |r|
|
198
|
-
r.order_values << (attribute.is_a?(Hash) ? attribute : {attribute.to_sym => :asc})
|
197
|
+
r.order_values << (attribute.is_a?(Hash) ? attribute : { attribute.to_sym => :asc })
|
199
198
|
end
|
200
199
|
end
|
201
|
-
|
200
|
+
|
202
201
|
# Orders the result set in memory after all matching records have been
|
203
202
|
# retrieved.
|
204
203
|
#
|
@@ -219,10 +218,10 @@ module DatastaxRails
|
|
219
218
|
def slow_order(attribute)
|
220
219
|
return self if attribute.blank?
|
221
220
|
clone.tap do |r|
|
222
|
-
r.slow_order_values << (attribute.is_a?(Hash) ? attribute : {attribute.to_sym => :asc})
|
221
|
+
r.slow_order_values << (attribute.is_a?(Hash) ? attribute : { attribute.to_sym => :asc })
|
223
222
|
end
|
224
223
|
end
|
225
|
-
|
224
|
+
|
226
225
|
# Works in two unique ways.
|
227
226
|
#
|
228
227
|
# _First_: takes a block so it can be used just like Array#select.
|
@@ -256,7 +255,7 @@ module DatastaxRails
|
|
256
255
|
# In that case, it is never retrieved until you call the getter method.
|
257
256
|
def select(*fields)
|
258
257
|
if block_given?
|
259
|
-
to_a.select {|*block_args| yield(*block_args) }
|
258
|
+
to_a.select { |*block_args| yield(*block_args) }
|
260
259
|
else
|
261
260
|
railse ArgumentError, 'Call this with at least one field' if fields.empty?
|
262
261
|
clone.tap do |r|
|
@@ -264,11 +263,11 @@ module DatastaxRails
|
|
264
263
|
end
|
265
264
|
end
|
266
265
|
end
|
267
|
-
|
266
|
+
|
268
267
|
# Reverses the order of the results. The following are equivalent:
|
269
|
-
#
|
268
|
+
#
|
270
269
|
# Model.order(:name).reverse_order
|
271
|
-
# Model.order(name: :desc)
|
270
|
+
# Model.order(name: :desc)
|
272
271
|
#
|
273
272
|
# Model.order(:name).reverse_order.reverse_order
|
274
273
|
# Model.order(name: :asc)
|
@@ -279,7 +278,7 @@ module DatastaxRails
|
|
279
278
|
r.reverse_order_value == !r.reverse_order_value
|
280
279
|
end
|
281
280
|
end
|
282
|
-
|
281
|
+
|
283
282
|
# By default, DatastaxRails uses the LuceneQueryParser. disMax
|
284
283
|
# is also supported. eDisMax probably works as well.
|
285
284
|
#
|
@@ -287,16 +286,16 @@ module DatastaxRails
|
|
287
286
|
#
|
288
287
|
# Model.query_parser('disMax').fulltext("john smith")
|
289
288
|
#
|
290
|
-
# @param parser [String] the parser to use for the fulltext query
|
289
|
+
# @param parser [String] the parser to use for the fulltext query
|
291
290
|
# @return [DatastaxRails::Relation] a new Relation object
|
292
291
|
def query_parser(parser)
|
293
292
|
return self if parser.blank?
|
294
|
-
|
293
|
+
|
295
294
|
clone.tap do |r|
|
296
295
|
r.query_parser_value = parser
|
297
296
|
end
|
298
297
|
end
|
299
|
-
|
298
|
+
|
300
299
|
# Have SOLR compute stats for a given numeric field. Status computed include:
|
301
300
|
# * min
|
302
301
|
# * max
|
@@ -315,12 +314,12 @@ module DatastaxRails
|
|
315
314
|
# @return [DatastaxRails::Relation] a new Relation object
|
316
315
|
def compute_stats(*fields)
|
317
316
|
return self if fields.empty?
|
318
|
-
|
317
|
+
|
319
318
|
clone.tap do |r|
|
320
319
|
r.stats_values += Array.wrap(fields)
|
321
320
|
end
|
322
321
|
end
|
323
|
-
|
322
|
+
|
324
323
|
# By default, DatastaxRails will try to pick the right method of performing
|
325
324
|
# a search. You can use this method to force it to make the query via SOLR.
|
326
325
|
#
|
@@ -335,7 +334,7 @@ module DatastaxRails
|
|
335
334
|
r.use_solr_value = true
|
336
335
|
end
|
337
336
|
end
|
338
|
-
|
337
|
+
|
339
338
|
# By default, DatastaxRails will try to pick the right method of performing
|
340
339
|
# a search. You can use this method to force it to make the query via
|
341
340
|
# cassandra.
|
@@ -349,7 +348,7 @@ module DatastaxRails
|
|
349
348
|
r.use_solr_value = false
|
350
349
|
end
|
351
350
|
end
|
352
|
-
|
351
|
+
|
353
352
|
# Specifies restrictions (scoping) on the result set. Expects a hash
|
354
353
|
# in the form +attribute: value+ for equality comparisons.
|
355
354
|
#
|
@@ -387,26 +386,26 @@ module DatastaxRails
|
|
387
386
|
else
|
388
387
|
clone.tap do |r|
|
389
388
|
attributes = attribute.dup
|
390
|
-
attributes.each do |k,v|
|
391
|
-
if
|
389
|
+
attributes.each do |k, v|
|
390
|
+
if v.is_a?(Hash)
|
392
391
|
comp, value = v.first
|
393
|
-
if(comp.to_s == 'greater_than')
|
394
|
-
r.greater_than_values << {k => value}
|
395
|
-
elsif(comp.to_s == 'less_than')
|
396
|
-
r.less_than_values << {k => value}
|
392
|
+
if (comp.to_s == 'greater_than')
|
393
|
+
r.greater_than_values << { k => value }
|
394
|
+
elsif (comp.to_s == 'less_than')
|
395
|
+
r.less_than_values << { k => value }
|
397
396
|
else
|
398
|
-
r.where_values << {k => value}
|
397
|
+
r.where_values << { k => value }
|
399
398
|
end
|
400
399
|
attributes.delete(k)
|
401
400
|
else
|
402
|
-
attributes[k] = solr_format(k,v)
|
401
|
+
attributes[k] = solr_format(k, v)
|
403
402
|
end
|
404
403
|
end
|
405
404
|
r.where_values << attributes unless attributes.empty?
|
406
405
|
end
|
407
406
|
end
|
408
407
|
end
|
409
|
-
|
408
|
+
|
410
409
|
# Specifies restrictions (scoping) that should not match the result set.
|
411
410
|
# Expects a hash in the form +attribute: value+.
|
412
411
|
#
|
@@ -425,32 +424,32 @@ module DatastaxRails
|
|
425
424
|
# or a proxy object if just an attribute was passed
|
426
425
|
def where_not(attribute)
|
427
426
|
return self if attribute.blank?
|
428
|
-
|
427
|
+
|
429
428
|
if attribute.is_a?(Symbol)
|
430
429
|
WhereProxy.new(self, attribute, true)
|
431
430
|
else
|
432
431
|
clone.tap do |r|
|
433
432
|
attributes = attribute.dup
|
434
|
-
attributes.each do |k,v|
|
435
|
-
if
|
433
|
+
attributes.each do |k, v|
|
434
|
+
if v.is_a?(Hash)
|
436
435
|
comp, value = v.first
|
437
|
-
if(comp.to_s == 'greater_than')
|
438
|
-
r.less_than_values << {k => value}
|
439
|
-
elsif(comp.to_s == 'less_than')
|
440
|
-
r.greater_than_values << {k => value}
|
436
|
+
if (comp.to_s == 'greater_than')
|
437
|
+
r.less_than_values << { k => value }
|
438
|
+
elsif (comp.to_s == 'less_than')
|
439
|
+
r.greater_than_values << { k => value }
|
441
440
|
else
|
442
|
-
r.where_not_values << {k => value}
|
441
|
+
r.where_not_values << { k => value }
|
443
442
|
end
|
444
443
|
attributes.delete(k)
|
445
444
|
else
|
446
|
-
attributes[k] = solr_format(k,v)
|
445
|
+
attributes[k] = solr_format(k, v)
|
447
446
|
end
|
448
447
|
end
|
449
448
|
r.where_not_values << attributes unless attributes.empty?
|
450
449
|
end
|
451
450
|
end
|
452
451
|
end
|
453
|
-
|
452
|
+
|
454
453
|
# Specifies a full text search string to be processed by SOLR
|
455
454
|
#
|
456
455
|
# Model.fulltext("john smith")
|
@@ -467,21 +466,21 @@ module DatastaxRails
|
|
467
466
|
# @return [DatastaxRails::Relation] a new Relation object
|
468
467
|
def fulltext(query, opts = {})
|
469
468
|
return self if query.blank?
|
470
|
-
|
469
|
+
|
471
470
|
opts[:query] = downcase_query(query)
|
472
|
-
|
471
|
+
|
473
472
|
clone.tap do |r|
|
474
473
|
r.fulltext_values << opts
|
475
474
|
end
|
476
475
|
end
|
477
|
-
|
478
|
-
# Enables highlighting on specific fields when used with full
|
479
|
-
# text searching. In order for highlighting to work, the highlighted
|
476
|
+
|
477
|
+
# Enables highlighting on specific fields when used with full
|
478
|
+
# text searching. In order for highlighting to work, the highlighted
|
480
479
|
# field(s) *must* be +:stored+
|
481
|
-
#
|
480
|
+
#
|
482
481
|
# Model.fulltext("ruby on rails").highlight(:tags, :body)
|
483
482
|
# Model.fulltext("pizza").highlight(:description, snippets: 3, fragsize: 150)
|
484
|
-
#
|
483
|
+
#
|
485
484
|
# In addition to the array of field names to highlight, you can pass in an
|
486
485
|
# options hash with the following options:
|
487
486
|
#
|
@@ -491,10 +490,10 @@ module DatastaxRails
|
|
491
490
|
# * :post_tag => text which appears after a highlighted term
|
492
491
|
# * :merge_contiguous => collapse contiguous fragments into a single fragment
|
493
492
|
# * :use_fast_vector => enables the Solr FastVectorHighlighter
|
494
|
-
#
|
493
|
+
#
|
495
494
|
# Note: When enabling +:use_fast_vector+, the highlighted fields must be also have
|
496
|
-
# +:term_vectors+, +:term_positions+, and +:term_offsets+ enabled.
|
497
|
-
# For more information about these options, refer to Solr's wiki
|
495
|
+
# +:term_vectors+, +:term_positions+, and +:term_offsets+ enabled.
|
496
|
+
# For more information about these options, refer to Solr's wiki
|
498
497
|
# on HighlightingParameters[http://http://wiki.apache.org/solr/HighlightingParameters].
|
499
498
|
#
|
500
499
|
# @overload highlight(*args, opts)
|
@@ -515,50 +514,51 @@ module DatastaxRails
|
|
515
514
|
# @return [DatastaxRails::Relation] a new Relation object
|
516
515
|
def highlight(*args)
|
517
516
|
return self if args.blank?
|
518
|
-
|
517
|
+
|
519
518
|
opts = args.last.is_a?(Hash) ? args.pop : {}
|
520
|
-
|
519
|
+
|
521
520
|
clone.tap do |r|
|
522
521
|
opts[:fields] = r.highlight_options[:fields] || []
|
523
522
|
opts[:fields] |= args # Union unique field names
|
524
523
|
r.highlight_options.merge! opts
|
525
524
|
end
|
526
525
|
end
|
527
|
-
|
526
|
+
|
528
527
|
# @see where
|
529
|
-
def less_than(
|
530
|
-
|
528
|
+
def less_than(_value)
|
529
|
+
fail(ArgumentError, '#less_than can only be called after an appropriate where call. ' \
|
530
|
+
'e.g. where(:created_at).less_than(1.day.ago)')
|
531
531
|
end
|
532
|
-
|
532
|
+
|
533
533
|
# @see where
|
534
|
-
def greater_than(
|
535
|
-
|
534
|
+
def greater_than(_value)
|
535
|
+
fail(ArgumentError, '#greater_than can only be called after an appropriate where call. ' \
|
536
|
+
'e.g. where(:created_at).greater_than(1.day.ago)')
|
536
537
|
end
|
537
|
-
|
538
|
+
|
538
539
|
# Formats a value for solr (assuming this is a solr query).
|
539
|
-
def solr_format(attribute, value)
|
540
|
+
def solr_format(attribute, value) # rubocop:disable Style/CyclomaticComplexity
|
540
541
|
return value unless use_solr_value
|
541
542
|
column = attribute.is_a?(DatastaxRails::Column) ? attribute : klass.column_for_attribute(attribute)
|
542
543
|
# value = column.type_cast_for_solr(value)
|
543
544
|
case
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
545
|
+
when value.is_a?(Time) || value.is_a?(DateTime) || value.is_a?(Date)
|
546
|
+
column.type_cast_for_solr(value)
|
547
|
+
when value.is_a?(Array) || value.is_a?(Set)
|
548
|
+
column.type_cast_for_solr(value).map { |v| v.to_s.gsub(/ /, '\\ ') }.join(' OR ')
|
549
|
+
when value.is_a?(Fixnum)
|
550
|
+
value < 0 ? "\\#{value}" : value
|
551
|
+
when value.is_a?(Range)
|
552
|
+
"[#{solr_format(attribute, value.first)} TO #{solr_format(attribute, value.last)}]"
|
553
|
+
when value.is_a?(String)
|
554
|
+
solr_escape(downcase_query(value.gsub(/ /, '\\ ')))
|
555
|
+
when value.is_a?(FalseClass), value.is_a?(TrueClass)
|
556
|
+
value.to_s
|
557
|
+
else
|
558
|
+
value
|
559
559
|
end
|
560
560
|
end
|
561
|
-
|
561
|
+
|
562
562
|
# WhereProxy objects act as a placeholder for queries in which #where does not include a value.
|
563
563
|
# In this case, #where must be chained with #greater_than, #less_than, or #equal_to to return
|
564
564
|
# a new relation.
|
@@ -566,33 +566,33 @@ module DatastaxRails
|
|
566
566
|
def initialize(relation, attribute, invert = false) #:nodoc:
|
567
567
|
@relation, @attribute, @invert = relation, attribute, invert
|
568
568
|
end
|
569
|
-
|
569
|
+
|
570
570
|
def equal_to(value) #:nodoc:
|
571
571
|
@relation.clone.tap do |r|
|
572
572
|
if @invert
|
573
|
-
r.where_not_values << {@attribute => r.solr_format(@attribute, value)}
|
573
|
+
r.where_not_values << { @attribute => r.solr_format(@attribute, value) }
|
574
574
|
else
|
575
|
-
r.where_values << {@attribute => r.solr_format(@attribute, value)}
|
575
|
+
r.where_values << { @attribute => r.solr_format(@attribute, value) }
|
576
576
|
end
|
577
577
|
end
|
578
578
|
end
|
579
|
-
|
579
|
+
|
580
580
|
def greater_than(value) #:nodoc:
|
581
581
|
@relation.clone.tap do |r|
|
582
582
|
if @invert
|
583
|
-
r.less_than_values << {@attribute => r.solr_format(@attribute, value)}
|
583
|
+
r.less_than_values << { @attribute => r.solr_format(@attribute, value) }
|
584
584
|
else
|
585
|
-
r.greater_than_values << {@attribute => r.solr_format(@attribute, value)}
|
585
|
+
r.greater_than_values << { @attribute => r.solr_format(@attribute, value) }
|
586
586
|
end
|
587
587
|
end
|
588
588
|
end
|
589
|
-
|
589
|
+
|
590
590
|
def less_than(value) #:nodoc:
|
591
591
|
@relation.clone.tap do |r|
|
592
592
|
if @invert
|
593
|
-
r.greater_than_values << {@attribute => r.solr_format(@attribute, value)}
|
593
|
+
r.greater_than_values << { @attribute => r.solr_format(@attribute, value) }
|
594
594
|
else
|
595
|
-
r.less_than_values << {@attribute => r.solr_format(@attribute, value)}
|
595
|
+
r.less_than_values << { @attribute => r.solr_format(@attribute, value) }
|
596
596
|
end
|
597
597
|
end
|
598
598
|
end
|