datastax_rails 2.0.12 → 2.0.15
Sign up to get free protection for your applications and to get access to all the features.
- 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
|