datastax_rails 1.0.15 → 1.0.16.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,9 @@
1
1
  module DatastaxRails
2
2
  class Collection < Array
3
+ # @!attribute [r] total_entries
4
+ # @return [Fixnum] the total number of entries that match the search
5
+ # @!attribute [r] last_column_name
6
+ # @return [Fixnum] the last column that was returned in the search in case you limited the number of columns (not supported)
3
7
  attr_accessor :last_column_name, :total_entries
4
8
 
5
9
  def inspect
@@ -1,4 +1,6 @@
1
1
  # require 'datastax_rails/rsolr_client_wrapper'
2
+ require 'rsolr/client_cert'
3
+ require 'rest_client'
2
4
  module DatastaxRails
3
5
  # The connection module holds all the code for establishing and maintaining a connection to
4
6
  # Datastax Exterprise. This includes both the Cassandra and Solr connections.
@@ -13,7 +15,8 @@ module DatastaxRails
13
15
  module ClassMethods
14
16
  DEFAULT_OPTIONS = {
15
17
  :servers => "127.0.0.1:9160",
16
- :thrift => {}
18
+ :thrift => {},
19
+ :cql_version => '3.0.0'
17
20
  }
18
21
 
19
22
  # Returns the current server that we are talking to. This is useful when you are talking to a
@@ -48,6 +51,11 @@ module DatastaxRails
48
51
  # solr:
49
52
  # port: 8983
50
53
  # path: /solr
54
+ # ssl:
55
+ # use_ssl: true
56
+ # cert: config/datastax_rails.crt
57
+ # key: config/datastax_rails.key
58
+ # keypass: changeme
51
59
  #
52
60
  # The +servers+ entry should be a list of all of the servers in your local datacenter. These
53
61
  # are the servers that DSR will attempt to connect to and will round-robin through.
@@ -85,26 +93,54 @@ module DatastaxRails
85
93
  DatastaxRails::Base.config = spec.with_indifferent_access
86
94
  spec.reverse_merge!(DEFAULT_OPTIONS)
87
95
  connection_options = spec[:connection_options] || {}
88
- self.connection = CassandraCQL::Database.new(spec[:servers], {:keyspace => spec[:keyspace]}, connection_options.symbolize_keys)
96
+ self.connection = CassandraCQL::Database.new(spec[:servers], {:keyspace => spec[:keyspace], :cql_version => spec[:cql_version]}, connection_options.symbolize_keys)
89
97
  end
90
98
 
91
99
  # Returns the base portion of the URL for connecting to SOLR based on the current Cassandra server.
92
100
  #
93
101
  # @return [String] in the form of 'http://localhost:8983/solr'
94
102
  def solr_base_url
95
- DatastaxRails::Base.establish_connection unless self.connection
103
+ DatastaxRails::Base.establish_connection unless self.connection
96
104
  port = DatastaxRails::Base.config[:solr][:port]
97
105
  path = DatastaxRails::Base.config[:solr][:path]
98
- "http://#{self.current_server}:#{port}#{path}"
106
+ protocol = DatastaxRails::Base.config[:solr].has_key?(:ssl) && DatastaxRails::Base.config[:solr][:ssl][:use_ssl] ? 'https' : 'http'
107
+ "#{protocol}://#{self.current_server}:#{port}#{path}"
108
+ end
109
+
110
+ # Wraps and caches a solr connection object
111
+ #
112
+ # @params [Boolean] reconnect force a new connection
113
+ # @return [DatastaxRails::RSolrClientWrapper] a wrapped RSolr connection
114
+ def solr_connection(reconnect = false)
115
+ if(!@rsolr || reconnect)
116
+ @rsolr = DatastaxRails::RSolrClientWrapper.new(establish_solr_connection)
117
+ end
118
+ @rsolr
99
119
  end
100
120
 
101
121
  # Similar to +establish_connection+, this method creates a connection object for Solr. Since HTTP is stateless, this doesn't
102
122
  # actually launch the connection, but it gets everything set up so that RSolr can do its work. It's important to note that
103
123
  # unlike the cassandra connection which is global to all of DSR, each model will have its own solr_connection.
104
124
  #
105
- # @return [DatastaxRails::RSolrClientWrapper] a wrapped RSolr connection
106
- def solr_connection
107
- @rsolr ||= DatastaxRails::RSolrClientWrapper.new(RSolr.connect :url => "#{solr_base_url}/#{DatastaxRails::Base.connection.keyspace}.#{self.column_family}")
125
+ # @return [RSolr::Client] RSolr client object
126
+ def establish_solr_connection
127
+ opts = {:url => "#{solr_base_url}/#{DatastaxRails::Base.connection.keyspace}.#{self.column_family}"}
128
+ if DatastaxRails::Base.config[:solr].has_key?(:ssl) &&
129
+ DatastaxRails::Base.config[:solr][:ssl].has_key?(:cert) &&
130
+ DatastaxRails::Base.config[:solr][:ssl][:use_ssl]
131
+ cert = Pathname.new(DatastaxRails::Base.config[:solr][:ssl][:cert])
132
+ key = Pathname.new(DatastaxRails::Base.config[:solr][:ssl][:key])
133
+ pass = DatastaxRails::Base.config[:solr][:ssl][:keypass]
134
+ cert = Rails.root.join(cert) unless cert.absolute?
135
+ key = Rails.root.join(key) unless key.absolute?
136
+ opts[:ssl_cert_file] = cert.to_s
137
+ opts[:ssl_key_file] = key.to_s
138
+ opts[:ssl_key_pass] = pass if pass
139
+
140
+ RSolr::ClientCert.connect opts
141
+ else
142
+ RSolr.connect opts
143
+ end
108
144
  end
109
145
  end
110
146
  end
@@ -16,7 +16,6 @@ module DatastaxRails
16
16
  # already been set up (Rails does this for you).
17
17
  def execute
18
18
  cql = self.to_cql
19
- Rails.logger.debug(cql)
20
19
  DatastaxRails::Base.connection.execute_cql_query(cql)
21
20
  end
22
21
  end
@@ -34,38 +34,40 @@ module DatastaxRails
34
34
  end
35
35
 
36
36
  def to_cql
37
- columns = @columns.dup
38
- values = []
39
-
40
- stmt = "update #{@klass.column_family} using consistency #{@consistency} "
41
-
42
- if(@ttl)
43
- stmt << "AND TTL #{@ttl} "
44
- end
45
-
46
- if(@timestamp)
47
- stmt << "AND TIMESTAMP #{@timestamp}"
48
- end
49
-
50
- unless columns.empty?
51
- stmt << "SET "
37
+ column_names = @columns.keys
38
+ cql = ""
39
+ Tempfile.open('cql', Rails.root.join("tmp")) do |stmt|
40
+ stmt << "update #{@klass.column_family} using consistency #{@consistency} "
52
41
 
53
- first_entry = columns.shift
42
+ if(@ttl)
43
+ stmt << "AND TTL #{@ttl} "
44
+ end
54
45
 
55
- stmt << "#{first_entry.first.to_s} = ?"
56
- values << first_entry.last
46
+ if(@timestamp)
47
+ stmt << "AND TIMESTAMP #{@timestamp}"
48
+ end
57
49
 
58
- columns.each do |k,v|
59
- stmt << ", #{k.to_s} = ?"
60
- values << v
50
+ unless @columns.empty?
51
+ stmt << "SET "
52
+
53
+ first_entry = column_names.first
54
+
55
+ stmt << CassandraCQL::Statement.sanitize("#{first_entry.to_s} = ?", [@columns[first_entry]])
56
+ column_names[1..-1].each do |col|
57
+ stmt << CassandraCQL::Statement.sanitize(", #{col.to_s} = ?", [@columns[col]])
58
+ end
61
59
  end
60
+
61
+ stmt << CassandraCQL::Statement.sanitize(" WHERE KEY IN (?)", [@key])
62
+ stmt.rewind
63
+ cql = stmt.read
62
64
  end
63
-
64
- stmt << " WHERE KEY IN (?)"
65
- values << @key
66
-
67
- CassandraCQL::Statement.sanitize(stmt, values)
65
+ cql
68
66
  end
67
+
68
+ # def execute
69
+ # puts to_cql.truncate(50)
70
+ # end
69
71
  end
70
72
  end
71
73
  end
@@ -1,5 +1,13 @@
1
1
  module DatastaxRails
2
+ # GroupedCollection extends Hash to add some additional metadata. The hash keys will be the values
3
+ # for the thing that was grouped on. The hash entries point to instances of DatastaxRails::Collection.
2
4
  class GroupedCollection < Hash
5
+ # @!attribute [r] total_entries
6
+ # @return [Fixnum] the total number of entries *in the largest group*. This is to allow will_paginate to work properly.
7
+ # @!attribute [r] total_groups
8
+ # @return [Fixnum] the total number of groups if the groups were paginated (not supported yet)
9
+ # @!attribute [r] total_for_all
10
+ # @return [Fixnum] the total number of entries across all groups that match this search
3
11
  attr_accessor :total_entries, :total_groups, :total_for_all
4
12
 
5
13
  def inspect
@@ -72,6 +72,10 @@ module DatastaxRails
72
72
  end
73
73
  end
74
74
  end
75
+
76
+ def store_file(key, file, options = {})
77
+
78
+ end
75
79
 
76
80
  # Instantiates a new object without calling +initialize+.
77
81
  #
@@ -1,3 +1,4 @@
1
+ require 'rubygems'
1
2
  require 'datastax_rails'
2
3
  require 'rails'
3
4
  module DatastaxRails
@@ -17,4 +18,4 @@ module DatastaxRails
17
18
  # require 'datastax_rails/generators/migration_generator'
18
19
  # end
19
20
  end
20
- end
21
+ end
@@ -15,6 +15,9 @@ module DatastaxRails
15
15
  # been updated yet with the results. In practice, this should not happen for
16
16
  # records that were created over your connection, but it is possible for other
17
17
  # connections to create records that you can't see yet.
18
+ #
19
+ # @param level [Symbol, String] the level to set the consistency at
20
+ # @return [DatastaxRails::Relation] a new Relation object
18
21
  def consistency(level)
19
22
  level = level.to_s.upcase
20
23
  unless self.valid_consistency?(level)
@@ -34,6 +37,8 @@ module DatastaxRails
34
37
  #
35
38
  # Note that fulltext searches are NEVER escaped. Use Relation.solr_escape if you
36
39
  # want that done.
40
+ #
41
+ # @return [DatastaxRails::Relation] a new Relation object
37
42
  def dont_escape
38
43
  clone.tap do |r|
39
44
  r.escape_value = false
@@ -44,6 +49,9 @@ module DatastaxRails
44
49
  # a module or a block provided
45
50
  #
46
51
  # The object returned is a relation which can be further extended
52
+ #
53
+ # @param modules [Proc] one or more proc objects
54
+ # @return [DatastaxRails::Relation] a new Relation object
47
55
  def extending(*modules)
48
56
  modules << Module.new(&Proc.new) if block_given?
49
57
 
@@ -69,6 +77,9 @@ module DatastaxRails
69
77
  # 30
70
78
  # end
71
79
  # end
80
+ #
81
+ # @param value [String, Fixnum] the number of records to include on a page
82
+ # @return [DatastaxRails::Relation] a new Relation object
72
83
  def limit(value)
73
84
  clone.tap do |r|
74
85
  r.per_page_value = value.to_i
@@ -79,6 +90,9 @@ module DatastaxRails
79
90
  # Sets the page number to retrieve
80
91
  #
81
92
  # Model.page(2)
93
+ #
94
+ # @param value [String, Fixnum] the page number to retrieve
95
+ # @return [DatastaxRails::Relation] a new Relation object
82
96
  def page(value)
83
97
  clone.tap do |r|
84
98
  r.page_value = value.to_i
@@ -88,6 +102,10 @@ module DatastaxRails
88
102
  # WillPaginate compatible method for paginating
89
103
  #
90
104
  # Model.paginate(:page => 2, :per_page => 10)
105
+ # @param options [Hash] the options to pass to paginate
106
+ # @option options [String, Fixnum] :page the page number to retrieve
107
+ # @option options [String, Fixnum] :per_page the number of records to include on a page
108
+ # @return [DatastaxRails::Relation] a new Relation object
91
109
  def paginate(options = {})
92
110
  options = options.reverse_merge({:page => 1, :per_page => 30})
93
111
  clone.tap do |r|
@@ -102,7 +120,7 @@ module DatastaxRails
102
120
  # This modifies the behavior of pagination. When using a group, +per_page+ will
103
121
  # specify the number of results returned *for each group*. In addition, +page+
104
122
  # will move all groups forward by one page possibly resulting in some groups
105
- # getting dropped off if they have fewer matching entires than others.
123
+ # showing up empty if they have fewer matching entires than others.
106
124
  #
107
125
  # When grouping is being used, the sort values will be used to sort results within
108
126
  # a given group. Any sorting of the groups themselves will need to be handled
@@ -115,6 +133,11 @@ module DatastaxRails
115
133
  # NOTE: Group names will be lower-cased
116
134
  #
117
135
  # Model.group(:program_id)
136
+ #
137
+ # The object the hash entries point to will be a DatastaxRails::Collection
138
+ #
139
+ # @param attribute [Symbol, String] the attribute to group by
140
+ # @return [DatastaxRails::Relation] a new Relation object
118
141
  def group(attribute)
119
142
  return self if attribute.blank?
120
143
 
@@ -133,6 +156,9 @@ module DatastaxRails
133
156
  #
134
157
  # Model.order(:name)
135
158
  # Model.order(:name => :desc)
159
+ #
160
+ # @param attribute [Symbol, String, Hash] the attribute to sort by and optionally the direction to sort in
161
+ # @return [DatastaxRails::Relation] a new Relation object
136
162
  def order(attribute)
137
163
  return self if attribute.blank?
138
164
 
@@ -184,15 +210,15 @@ module DatastaxRails
184
210
  end
185
211
  end
186
212
 
187
- # Reverses the order of the results
213
+ # Reverses the order of the results. The following are equivalent:
188
214
  #
189
215
  # Model.order(:name).reverse_order
190
- # is equivalent to
191
- # Model.order(:name => :desc)
216
+ # Model.order(:name => :desc)
192
217
  #
193
218
  # Model.order(:name).reverse_order.reverse_order
194
- # is equivalent to
195
219
  # Model.order(:name => :asc)
220
+ #
221
+ # @return [DatastaxRails::Relation] a new Relation object
196
222
  def reverse_order
197
223
  clone.tap do |r|
198
224
  r.reverse_order_value == !r.reverse_order_value
@@ -206,11 +232,14 @@ module DatastaxRails
206
232
  # *This only applies to fulltext queries*
207
233
  #
208
234
  # Model.query_parser('disMax').fulltext("john smith")
209
- def query_parser(attribute)
210
- return self if attribute.blank?
235
+ #
236
+ # @param parser [String] the parser to use for the fulltext query
237
+ # @return [DatastaxRails::Relation] a new Relation object
238
+ def query_parser(parser)
239
+ return self if parser.blank?
211
240
 
212
241
  clone.tap do |r|
213
- r.query_parser_value = attribute
242
+ r.query_parser_value = parser
214
243
  end
215
244
  end
216
245
 
@@ -221,6 +250,8 @@ module DatastaxRails
221
250
  # it becomes available in SOLR is not guaranteed to be insignificant. It's
222
251
  # very possible to insert a new record and not find it when immediately doing
223
252
  # a SOLR search for it.
253
+ #
254
+ # @return [DatastaxRails::Relation] a new Relation object
224
255
  def with_solr
225
256
  clone.tap do |r|
226
257
  r.use_solr_value = true
@@ -232,7 +263,9 @@ module DatastaxRails
232
263
  # cassandra.
233
264
  #
234
265
  # NOTE that this method assumes that you have all the proper secondary indexes
235
- # in place before you attempt to use it. If not, you will get an error.
266
+ # in place before you attempt to use it. If not, you will get an error.
267
+ #
268
+ # @return [DatastaxRails::Relation] a new Relation object
236
269
  def with_cassandra
237
270
  clone.tap do |r|
238
271
  r.use_solr_value = false
@@ -255,21 +288,43 @@ module DatastaxRails
255
288
  # Model.where(:created_at).greater_than(1.day.ago)
256
289
  # Model.where(:age).less_than(65)
257
290
  #
291
+ # There is an alternate form of specifying greater than/less than queries
292
+ # that can be done with a single call. This is useful for remote APIs and
293
+ # such.
294
+ #
295
+ # Model.where(:created_at => {:greater_than => 1.day.ago})
296
+ # Model.where(:age => {:less_than => 65})
297
+ #
258
298
  # NOTE: Due to the way SOLR handles range queries, all greater/less than
259
- # queries are actually greater/less than or equal to queries.
260
- # There is no way to perform a strictly greater/less than query.
299
+ # queries are actually greater/less than or equal to queries.
300
+ # There is no way to perform a strictly greater/less than query.
301
+ #
302
+ # @param attribute [Symbol, String, Hash] a hash of conditions or a single attribute that will be followed by
303
+ # greater_than or less_than
304
+ # @return [DatastaxRails::Relation] a new Relation object
261
305
  def where(attribute)
262
306
  return self if attribute.blank?
263
-
264
307
  if attribute.is_a?(Symbol)
265
308
  WhereProxy.new(self, attribute)
266
309
  else
267
- attributes = attribute.dup
268
- attributes.each do |k,v|
269
- attributes[k] = solr_format(v)
270
- end
271
310
  clone.tap do |r|
272
- r.where_values << attributes
311
+ attributes = attribute.dup
312
+ attributes.each do |k,v|
313
+ if(v.is_a?(Hash))
314
+ comp, value = v.first
315
+ if(comp.to_s == 'greater_than')
316
+ r.greater_than_values << {k => value}
317
+ elsif(comp.to_s == 'less_than')
318
+ r.less_than_values << {k => value}
319
+ else
320
+ r.where_values << {k => value}
321
+ end
322
+ attributes.delete(k)
323
+ else
324
+ attributes[k] = solr_format(v)
325
+ end
326
+ end
327
+ r.where_values << attributes unless attributes.empty?
273
328
  end
274
329
  end
275
330
  end
@@ -285,22 +340,37 @@ module DatastaxRails
285
340
  # Model.where_not(:group_id => ['1234', '5678'])
286
341
  #
287
342
  # The above would find all models where group id is neither 1234 or 5678.
343
+ #
344
+ # @param attribute [Symbol, String, Hash] a hash of conditions or a single attribute that will be followed by
345
+ # greater_than or less_than
346
+ # @return [DatastaxRails::Relation, DatastaxRails::SearchMethods::WhereProxy] a new Relation object
347
+ # or a proxy object if just an attribute was passed
288
348
  def where_not(attribute)
289
349
  return self if attribute.blank?
290
350
 
291
- attributes = []
292
- attribute.each do |k,v|
293
- if v.is_a?(Array)
294
- v.each do |val|
295
- attributes << {k => solr_format(val)}
351
+ if attribute.is_a?(Symbol)
352
+ WhereProxy.new(self, attribute, true)
353
+ else
354
+ clone.tap do |r|
355
+ attributes = attribute.dup
356
+ attributes.each do |k,v|
357
+ if(v.is_a?(Hash))
358
+ comp, value = v.first
359
+ if(comp.to_s == 'greater_than')
360
+ r.less_than_values << {k => value}
361
+ elsif(comp.to_s == 'less_than')
362
+ r.greater_than_values << {k => value}
363
+ else
364
+ r.where_not_values << {k => value}
365
+ end
366
+ attributes.delete(k)
367
+ else
368
+ attributes[k] = solr_format(v)
369
+ end
296
370
  end
297
- else
298
- attributes << {k => solr_format(v)}
371
+ r.where_not_values << attributes unless attributes.empty?
299
372
  end
300
373
  end
301
- clone.tap do |r|
302
- r.where_not_values += attributes
303
- end
304
374
  end
305
375
 
306
376
  # Specifies a full text search string to be processed by SOLR
@@ -314,6 +384,12 @@ module DatastaxRails
314
384
  #
315
385
  # Model.fulltext("john smith", :fields => [:title])
316
386
  # Model.fulltext("john smith", :hightlight => [:body])
387
+ #
388
+ # @param query [String] a fulltext query to pass to solr
389
+ # @param opts [Hash] an optional options hash to modify the fulltext query
390
+ # @option opts [Array] :fields list of fields to search instead of the default of all text fields (not-implemented)
391
+ # @option opts [Array] :highlight list of fields to retrieve highlights for (not-implemented)
392
+ # @return [DatastaxRails::Relation] a new Relation object
317
393
  def fulltext(query, opts = {})
318
394
  return self if query.blank?
319
395
 
@@ -367,25 +443,37 @@ module DatastaxRails
367
443
  end
368
444
 
369
445
  class WhereProxy #:nodoc:
370
- def initialize(relation, attribute) #:nodoc:
371
- @relation, @attribute = relation, attribute
446
+ def initialize(relation, attribute, invert = false) #:nodoc:
447
+ @relation, @attribute, @invert = relation, attribute, invert
372
448
  end
373
449
 
374
450
  def equal_to(value) #:nodoc:
375
451
  @relation.clone.tap do |r|
376
- r.where_values << {@attribute => r.solr_format(value)}
452
+ if @invert
453
+ r.where_not_values << {@attribute => r.solr_format(value)}
454
+ else
455
+ r.where_values << {@attribute => r.solr_format(value)}
456
+ end
377
457
  end
378
458
  end
379
459
 
380
460
  def greater_than(value) #:nodoc:
381
461
  @relation.clone.tap do |r|
382
- r.greater_than_values << {@attribute => r.solr_format(value)}
462
+ if @invert
463
+ r.less_than_values << {@attribute => r.solr_format(value)}
464
+ else
465
+ r.greater_than_values << {@attribute => r.solr_format(value)}
466
+ end
383
467
  end
384
468
  end
385
469
 
386
470
  def less_than(value) #:nodoc:
387
471
  @relation.clone.tap do |r|
388
- r.less_than_values << {@attribute => r.solr_format(value)}
472
+ if @invert
473
+ r.greater_than_values << {@attribute => r.solr_format(value)}
474
+ else
475
+ r.less_than_values << {@attribute => r.solr_format(value)}
476
+ end
389
477
  end
390
478
  end
391
479
  end
@@ -86,20 +86,45 @@ module DatastaxRails
86
86
  result
87
87
  end
88
88
 
89
- VALID_FIND_OPTIONS = [:conditions, :limit, :select, :offset, :order, :group, :page, :per_page]
90
- def apply_finder_options(options) #:nodoc:
91
- relation = clone
89
+ VALID_FIND_OPTIONS = [:conditions, :limit, :select, :offset, :order, :group, :page, :per_page, :fulltext, :consistency, :with_solr, :with_cassandra, :where, :where_not]
90
+ # Applies the passed in finder options and returns a new Relation.
91
+ # Takes any of the options below and calls them on the relation as if they
92
+ # were methods (+conditions+ is passed to +where+).
93
+ #
94
+ # @param [Hash] options the options hash
95
+ # @option options [Hash] :conditions
96
+ # @option options [Symbol, String] :consistency
97
+ # @option options [String] :fulltext
98
+ # @option options [Symbol, String] :group
99
+ # @option options [Integer, String] :limit
100
+ # @option options [Integer, String] :offset
101
+ # @option options [String, Hash] :order
102
+ # @option options [Integer, String] :page
103
+ # @option options [Integer, String] :per_page
104
+ # @option options [Array] :select
105
+ # @option options [Hash] :where
106
+ # @option options [Hash] :where_not
107
+ # @option options [Boolean] :with_cassandra
108
+ # @option options [Boolean] :with_solr
109
+ # @return [DatastaxRails::Relation] relation with all options applied
110
+ # @raise [ArgumentError] if an invalid option is passed in
111
+ def apply_finder_options(options)
112
+ relation = self
92
113
  return relation unless options
93
114
 
94
115
  options.assert_valid_keys(VALID_FIND_OPTIONS)
95
116
  finders = options.dup
96
117
  finders.delete_if { |key, value| value.nil? }
97
118
 
98
- ([:group, :order, :limit, :offset, :page, :per_page, :select] & finders.keys).each do |finder|
99
- relation = relation.send(finder, finders[finder])
119
+ ((VALID_FIND_OPTIONS - [:conditions]) & finders.keys).each do |finder|
120
+ if(finder.to_s =~ /(with_solr|with_cassandra)/)
121
+ relation = relation.send(finder)
122
+ else
123
+ relation = relation.send(finder, finders[finder])
124
+ end
100
125
  end
101
126
 
102
- relation = relation.where(finders[:conditions]) if options.has_key?(:conditions)
127
+ relation = relation.where(finders[:conditions]) if finders.has_key?(:conditions)
103
128
  relation
104
129
  end
105
130
  end
@@ -24,7 +24,13 @@ module DatastaxRails
24
24
  alias :loaded? :loaded
25
25
  alias :default_scoped? :default_scoped
26
26
 
27
- def initialize(klass, column_family) #:nodoc:
27
+ # Initializes the Relation. Defaults page value to 1, per_page to the class
28
+ # default, and solr use to true. Everything else gets defaulted to nil or
29
+ # empty.
30
+ #
31
+ # @param [Class] klass the child of DatastaxRails::Base that this relation searches
32
+ # @param [String, Symbol] column_family the name of the column family this relation searches
33
+ def initialize(klass, column_family)
28
34
  @klass, @column_family = klass, column_family
29
35
  @loaded = false
30
36
  @results = []
@@ -146,12 +152,14 @@ module DatastaxRails
146
152
  @results = []
147
153
  end
148
154
 
149
- def initialize_copy(other) #:nodoc:
155
+ # Copies will have changes made to the criteria and so need to be reset.
156
+ def initialize_copy(other)
150
157
  reset
151
158
  @search = nil
152
159
  end
153
160
 
154
- def clone #:nodoc:
161
+ # Performs a deep copy using Marshal when cloning.
162
+ def clone
155
163
  dup.tap do |r|
156
164
  MULTI_VALUE_METHODS.each do |m|
157
165
  r.send("#{m}_values=", Marshal.load(Marshal.dump(self.send("#{m}_values"))))
@@ -210,7 +218,8 @@ module DatastaxRails
210
218
  scoping { @klass.create!(*args, &block) }
211
219
  end
212
220
 
213
- def respond_to?(method, include_private = false) #:nodoc:
221
+ # Override respond_to? so that it matches method_missing
222
+ def respond_to?(method, include_private = false)
214
223
  Array.method_defined?(method) ||
215
224
  @klass.respond_to?(method, include_private) ||
216
225
  super
@@ -339,7 +348,7 @@ module DatastaxRails
339
348
  params['group.limit'] = @per_page_value
340
349
  params['group.offset'] = (@page_value - 1) * @per_page_value
341
350
  params['group.ngroups'] = 'true'
342
- response = rsolr.post('select', :params => params)["grouped"][@group_value.to_s]
351
+ response = rsolr.post('select', :data => params)["grouped"][@group_value.to_s]
343
352
  results.total_groups = response['ngroups'].to_i
344
353
  results.total_for_all = response['matches'].to_i
345
354
  results.total_entries = 0
@@ -348,13 +357,18 @@ module DatastaxRails
348
357
  results.total_entries = results[group['groupValue']].total_entries if results[group['groupValue']].total_entries > results.total_entries
349
358
  end
350
359
  else
351
- response = rsolr.paginate(@page_value, @per_page_value, 'select', :params => params)["response"]
360
+ response = rsolr.paginate(@page_value, @per_page_value, 'select', :data => params, :method => :post)["response"]
352
361
  results = parse_docs(response, select_columns)
353
362
  end
354
363
  results
355
364
  end
356
365
 
357
-
366
+ # Parse out a set of documents and return the results
367
+ #
368
+ # @param response [Hash] the response hash from SOLR with a set of documents
369
+ # @param select_columns [Array] the columns that we actually selected from SOLR
370
+ #
371
+ # @return [DatastaxRails::Collection] the resulting collection
358
372
  def parse_docs(response, select_columns)
359
373
  results = DatastaxRails::Collection.new
360
374
  results.total_entries = response['numFound'].to_i
@@ -371,6 +385,10 @@ module DatastaxRails
371
385
  end
372
386
  protected(:parse_docs)
373
387
 
388
+ # Inspects the results of the search instead of the Relation itself.
389
+ # Passing true causes the Relation to be inspected.
390
+ #
391
+ # @param [Boolean] just_me if true, inspect the Relation, otherwise the results
374
392
  def inspect(just_me = false)
375
393
  just_me ? super() : to_a.inspect
376
394
  end
@@ -389,11 +407,14 @@ module DatastaxRails
389
407
  @klass.send(:with_scope, self, :overwrite) { yield }
390
408
  end
391
409
 
392
- def where_values_hash #:nodoc:
410
+ # Merges all of the where values together into a single hash
411
+ def where_values_hash
393
412
  where_values.inject({}) { |values,v| values.merge(v) }
394
413
  end
395
414
 
396
- def scope_for_create #:nodoc:
415
+ # Creates a scope that includes all of the where values plus anything
416
+ # that is in +create_with_value+.
417
+ def scope_for_create
397
418
  @scope_for_create ||= where_values_hash.merge(create_with_value)
398
419
  end
399
420
 
@@ -10,7 +10,7 @@ module DatastaxRails
10
10
  def method_missing(sym, *args, &block)
11
11
  if @rsolr.uri.host != DatastaxRails::Base.current_server
12
12
  @rsolr.uri.host = DatastaxRails::Base.current_server
13
- @rsolr = RSolr.connect(:url => @rsolr.uri.to_s)
13
+ @rsolr = DatastaxRails::Base.establish_solr_connection
14
14
  end
15
15
  @rsolr.__send__(sym, *args, &block)
16
16
  rescue Errno::ECONNREFUSED