parse-stack 1.7.3 → 1.9.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/ruby.yml +36 -0
  3. data/.solargraph.yml +23 -0
  4. data/.travis.yml +6 -3
  5. data/Changes.md +84 -22
  6. data/Gemfile +14 -12
  7. data/Gemfile.lock +110 -60
  8. data/README.md +67 -24
  9. data/Rakefile +14 -14
  10. data/bin/parse-console +1 -0
  11. data/lib/parse/api/aggregate.rb +59 -0
  12. data/lib/parse/api/all.rb +2 -1
  13. data/lib/parse/api/analytics.rb +0 -3
  14. data/lib/parse/api/batch.rb +3 -5
  15. data/lib/parse/api/cloud_functions.rb +0 -3
  16. data/lib/parse/api/config.rb +0 -4
  17. data/lib/parse/api/files.rb +3 -7
  18. data/lib/parse/api/hooks.rb +4 -8
  19. data/lib/parse/api/objects.rb +9 -14
  20. data/lib/parse/api/push.rb +0 -4
  21. data/lib/parse/api/schema.rb +2 -6
  22. data/lib/parse/api/server.rb +4 -7
  23. data/lib/parse/api/sessions.rb +2 -5
  24. data/lib/parse/api/users.rb +9 -14
  25. data/lib/parse/client.rb +55 -50
  26. data/lib/parse/client/authentication.rb +29 -33
  27. data/lib/parse/client/batch.rb +8 -11
  28. data/lib/parse/client/body_builder.rb +19 -20
  29. data/lib/parse/client/caching.rb +23 -28
  30. data/lib/parse/client/protocol.rb +11 -12
  31. data/lib/parse/client/request.rb +4 -6
  32. data/lib/parse/client/response.rb +5 -7
  33. data/lib/parse/model/acl.rb +14 -12
  34. data/lib/parse/model/associations/belongs_to.rb +19 -24
  35. data/lib/parse/model/associations/collection_proxy.rb +328 -317
  36. data/lib/parse/model/associations/has_many.rb +22 -27
  37. data/lib/parse/model/associations/has_one.rb +7 -12
  38. data/lib/parse/model/associations/pointer_collection_proxy.rb +5 -13
  39. data/lib/parse/model/associations/relation_collection_proxy.rb +5 -9
  40. data/lib/parse/model/bytes.rb +8 -10
  41. data/lib/parse/model/classes/installation.rb +2 -4
  42. data/lib/parse/model/classes/product.rb +2 -5
  43. data/lib/parse/model/classes/role.rb +3 -5
  44. data/lib/parse/model/classes/session.rb +2 -5
  45. data/lib/parse/model/classes/user.rb +21 -17
  46. data/lib/parse/model/core/actions.rb +31 -46
  47. data/lib/parse/model/core/builder.rb +6 -6
  48. data/lib/parse/model/core/errors.rb +0 -1
  49. data/lib/parse/model/core/fetching.rb +45 -50
  50. data/lib/parse/model/core/properties.rb +53 -68
  51. data/lib/parse/model/core/querying.rb +292 -282
  52. data/lib/parse/model/core/schema.rb +89 -92
  53. data/lib/parse/model/date.rb +16 -23
  54. data/lib/parse/model/file.rb +171 -174
  55. data/lib/parse/model/geopoint.rb +12 -16
  56. data/lib/parse/model/model.rb +31 -37
  57. data/lib/parse/model/object.rb +58 -70
  58. data/lib/parse/model/pointer.rb +177 -176
  59. data/lib/parse/model/push.rb +8 -10
  60. data/lib/parse/model/shortnames.rb +1 -2
  61. data/lib/parse/model/time_zone.rb +3 -5
  62. data/lib/parse/query.rb +70 -37
  63. data/lib/parse/query/constraint.rb +4 -6
  64. data/lib/parse/query/constraints.rb +62 -20
  65. data/lib/parse/query/operation.rb +8 -11
  66. data/lib/parse/query/ordering.rb +45 -49
  67. data/lib/parse/stack.rb +15 -11
  68. data/lib/parse/stack/generators/rails.rb +28 -30
  69. data/lib/parse/stack/generators/templates/model.erb +5 -6
  70. data/lib/parse/stack/generators/templates/model_installation.rb +0 -1
  71. data/lib/parse/stack/generators/templates/model_role.rb +0 -1
  72. data/lib/parse/stack/generators/templates/model_session.rb +0 -1
  73. data/lib/parse/stack/generators/templates/model_user.rb +0 -1
  74. data/lib/parse/stack/generators/templates/parse.rb +9 -9
  75. data/lib/parse/stack/generators/templates/webhooks.rb +1 -2
  76. data/lib/parse/stack/railtie.rb +2 -4
  77. data/lib/parse/stack/tasks.rb +70 -86
  78. data/lib/parse/stack/version.rb +1 -1
  79. data/lib/parse/webhooks.rb +19 -26
  80. data/lib/parse/webhooks/payload.rb +26 -28
  81. data/lib/parse/webhooks/registration.rb +23 -31
  82. data/parse-stack.gemspec +28 -28
  83. data/parse-stack.png +0 -0
  84. metadata +27 -25
  85. data/.github/parse-ruby-sdk.png +0 -0
@@ -5,11 +5,11 @@ require_relative "client"
5
5
  require_relative "query/operation"
6
6
  require_relative "query/constraints"
7
7
  require_relative "query/ordering"
8
- require 'active_model'
9
- require 'active_model_serializers'
10
- require 'active_support'
11
- require 'active_support/inflector'
12
- require 'active_support/core_ext'
8
+ require "active_model"
9
+ require "active_model_serializers"
10
+ require "active_support"
11
+ require "active_support/inflector"
12
+ require "active_support/core_ext"
13
13
 
14
14
  module Parse
15
15
  # The {Parse::Query} class provides the lower-level querying interface for
@@ -62,7 +62,7 @@ module Parse
62
62
  # You can build your own custom query constraints by creating a `Parse::Constraint`
63
63
  # subclass. For all these `where` clauses assume `q` is a `Parse::Query` object.
64
64
  class Query
65
- extend ::ActiveModel::Callbacks
65
+ extend ::ActiveModel::Callbacks
66
66
  include Parse::Client::Connectable
67
67
  include Enumerable
68
68
  # @!group Callbacks
@@ -196,8 +196,8 @@ module Parse
196
196
  # @param table [String] the name of the Parse collection to query. (ex. "_User")
197
197
  # @param constraints [Hash] a set of query constraints.
198
198
  # @return [Query] a new query for the Parse collection with the passed in constraints.
199
- def all(table, constraints = {limit: :max})
200
- self.new(table, constraints.reverse_merge({limit: :max}))
199
+ def all(table, constraints = { limit: :max })
200
+ self.new(table, constraints.reverse_merge({ limit: :max }))
201
201
  end
202
202
 
203
203
  # This methods takes a set of constraints and merges them to build a final
@@ -205,7 +205,7 @@ module Parse
205
205
  # @param where [Array] an array of {Parse::Constraint} objects.
206
206
  # @return [Hash] a hash representing the compiled query
207
207
  def compile_where(where)
208
- constraint_reduce( where )
208
+ constraint_reduce(where)
209
209
  end
210
210
 
211
211
  # @!visibility private
@@ -214,7 +214,7 @@ module Parse
214
214
  clauses.reduce({}) do |clause, subclause|
215
215
  #puts "Merging Subclause: #{subclause.as_json}"
216
216
 
217
- clause.deep_merge!( subclause.as_json || {} )
217
+ clause.deep_merge!(subclause.as_json || {})
218
218
  clause
219
219
  end
220
220
  end
@@ -228,7 +228,6 @@ module Parse
228
228
  query.define_singleton_method(:inspect) { self.results.to_a.inspect }
229
229
  end
230
230
  end
231
-
232
231
  end
233
232
 
234
233
  # @!attribute [r] client
@@ -314,7 +313,7 @@ module Parse
314
313
  elsif expression == :keys
315
314
  keys value
316
315
  elsif expression == :key
317
- @key = value
316
+ keys [value]
318
317
  elsif expression == :skip
319
318
  skip value
320
319
  elsif expression == :limit
@@ -334,6 +333,7 @@ module Parse
334
333
  end # each
335
334
  self #chaining
336
335
  end
336
+
337
337
  alias_method :query, :conditions
338
338
  alias_method :append, :conditions
339
339
 
@@ -418,7 +418,7 @@ module Parse
418
418
  # @param amount [Integer] The number of records to skip.
419
419
  # @return [self]
420
420
  def skip(amount)
421
- @skip = [0,amount.to_i].max
421
+ @skip = [0, amount.to_i].max
422
422
  @results = nil
423
423
  self #chaining
424
424
  end
@@ -434,11 +434,11 @@ module Parse
434
434
  # Song.all :limit => 2025 # large limits supported.
435
435
  # Song.all :limit => :max # as many records as possible.
436
436
  # @param count [Integer,Symbol] The number of records to return. You may pass :max
437
- # to get as many as 11_000 records with the aid if skipping.
437
+ # to get as many records as possible (Parse-Server dependent).
438
438
  # @return [self]
439
439
  def limit(count)
440
440
  if count.is_a?(Numeric)
441
- @limit = [ 0, count.to_i ].max
441
+ @limit = [0, count.to_i].max
442
442
  elsif count == :max
443
443
  @limit = :max
444
444
  else
@@ -497,10 +497,15 @@ module Parse
497
497
  # # add where :like_count is greater than 20
498
498
  # query.add_constraint(:like_count.gt, 20)
499
499
  #
500
+ # # same, but ignore field formatting
501
+ # query.add_constraint(:like_count.gt, 20, filter: false)
502
+ #
500
503
  # @param operator [Parse::Operator] an operator object containing the operation and operand.
501
504
  # @param value [Object] the value for the constraint.
505
+ # @param opts [Object] A set of options. Passing :filter with false, will skip field formatting.
506
+ # @see Query#format_field
502
507
  # @return [self]
503
- def add_constraint(operator, value = nil, **opts)
508
+ def add_constraint(operator, value = nil, opts = {})
504
509
  @where ||= []
505
510
  constraint = operator # assume Parse::Constraint
506
511
  unless constraint.is_a?(Parse::Constraint)
@@ -579,7 +584,7 @@ module Parse
579
584
  # @return [Query] the combined query with an OR clause.
580
585
  def or_where(where_clauses = [])
581
586
  where_clauses = where_clauses.where if where_clauses.is_a?(Parse::Query)
582
- where_clauses = Parse::Query.new(@table, where_clauses ).where if where_clauses.is_a?(Hash)
587
+ where_clauses = Parse::Query.new(@table, where_clauses).where if where_clauses.is_a?(Hash)
583
588
  return self if where_clauses.blank?
584
589
  # we can only have one compound query constraint. If we need to add another OR clause
585
590
  # let's find the one we have (if any)
@@ -589,7 +594,7 @@ module Parse
589
594
  # if we don't have a OR clause to reuse, then create a new one with then
590
595
  # current set of constraints
591
596
  if compound.blank?
592
- compound = Parse::Constraint::CompoundQueryConstraint.new :or, [ Parse::Query.compile_where(remaining_clauses) ]
597
+ compound = Parse::Constraint::CompoundQueryConstraint.new :or, [Parse::Query.compile_where(remaining_clauses)]
593
598
  end
594
599
  # then take the where clauses from the second query and append them.
595
600
  compound.value.push Parse::Query.compile_where(where_clauses)
@@ -601,10 +606,39 @@ module Parse
601
606
  # @see #or_where
602
607
  # @return [Query] the combined query with an OR clause.
603
608
  def |(other_query)
604
- raise ArgumentError, "Parse queries must be of the same class #{@table}." unless @table == other_query.table
605
- copy_query = self.clone
606
- copy_query.or_where other_query.where
607
- copy_query
609
+ raise ArgumentError, "Parse queries must be of the same class #{@table}." unless @table == other_query.table
610
+ copy_query = self.clone
611
+ copy_query.or_where other_query.where
612
+ copy_query
613
+ end
614
+
615
+ # Queries can be made using distinct, allowing you find unique values for a specified field.
616
+ # For this to be performant, please remember to index your database.
617
+ # @example
618
+ # # Return a set of unique city names
619
+ # # for users who are greater than 21 years old
620
+ # Parse::Query.all(distinct: :age)
621
+ # query = Parse::Query.new("_User")
622
+ # query.where :age.gt => 21
623
+ # # triggers query
624
+ # query.distinct(:city) #=> ["San Diego", "Los Angeles", "San Juan"]
625
+ # @note This feature requires use of the Master Key in the API.
626
+ # @param field [Symbol|String] The name of the field used for filtering.
627
+ # @version 1.8.0
628
+ def distinct(field)
629
+ if field.nil? == false && field.respond_to?(:to_s)
630
+ # disable counting if it was enabled.
631
+ old_count_value = @count
632
+ @count = nil
633
+ compile_query = compile # temporary store
634
+ # add distinct field
635
+ compile_query[:distinct] = Query.format_field(field).to_sym
636
+ @count = old_count_value
637
+ # perform aggregation
638
+ return client.aggregate_objects(@table, compile_query.as_json, _opts).result
639
+ else
640
+ raise ArgumentError, "Invalid field name passed to `distinct`."
641
+ end
608
642
  end
609
643
 
610
644
  # Perform a count query.
@@ -620,7 +654,7 @@ module Parse
620
654
  def count
621
655
  old_value = @count
622
656
  @count = 1
623
- res = client.find_objects(@table, compile.as_json, _opts ).count
657
+ res = client.find_objects(@table, compile.as_json, _opts).count
624
658
  @count = old_value
625
659
  res
626
660
  end
@@ -629,8 +663,8 @@ module Parse
629
663
  # @return [Array]
630
664
  # @see Array#each
631
665
  def each
632
- return results.enum_for(:each) unless block_given? # Sparkling magic!
633
- results.each(&Proc.new)
666
+ return results.enum_for(:each) unless block_given? # Sparkling magic!
667
+ results.each(&Proc.new)
634
668
  end
635
669
 
636
670
  # @yield a block yield for each object in the result
@@ -684,7 +718,7 @@ module Parse
684
718
  compiled_query[:limit] = _limit if _limit < batch_size
685
719
  end
686
720
 
687
- response = fetch!( compiled_query )
721
+ response = fetch!(compiled_query)
688
722
  break if response.error? || response.results.empty?
689
723
 
690
724
  items = response.results
@@ -732,13 +766,13 @@ module Parse
732
766
  # @param compiled_query [Hash] the compiled query
733
767
  # @return [Parse::Response] a response for a query request.
734
768
  def fetch!(compiled_query)
735
-
736
- response = client.find_objects(@table, compiled_query.as_json, _opts )
769
+ response = client.find_objects(@table, compiled_query.as_json, _opts)
737
770
  if response.error?
738
771
  puts "[ParseQuery] #{response.error}"
739
772
  end
740
773
  response
741
774
  end
775
+
742
776
  alias_method :execute!, :fetch!
743
777
 
744
778
  # Executes the query and builds the result set of Parse::Objects that matched.
@@ -767,7 +801,7 @@ module Parse
767
801
  if block_given?
768
802
  max_results(raw: raw, &Proc.new)
769
803
  elsif @limit.is_a?(Numeric)
770
- response = fetch!( compile )
804
+ response = fetch!(compile)
771
805
  return [] if response.error?
772
806
  items = raw ? response.results : decode(response.results)
773
807
  return items.each(&Proc.new) if block_given?
@@ -778,6 +812,7 @@ module Parse
778
812
  end
779
813
  @results
780
814
  end
815
+
781
816
  alias_method :result, :results
782
817
 
783
818
  # Similar to {#results} but takes an additional set of conditions to apply. This
@@ -787,7 +822,7 @@ module Parse
787
822
  # @return [Array<Hash>] if raw is set to true, a set of Parse JSON hashes.
788
823
  # @return [Array<Parse::Object>] if raw is set to false, a list of matching Parse::Object subclasses.
789
824
  # @see #results
790
- def all(expressions = {limit: :max})
825
+ def all(expressions = { limit: :max })
791
826
  conditions(expressions)
792
827
  return results(&Proc.new) if block_given?
793
828
  results
@@ -825,9 +860,9 @@ module Parse
825
860
  q[:limit] = @limit if @limit.is_a?(Numeric) && @limit > 0
826
861
  q[:skip] = @skip if @skip > 0
827
862
 
828
- q[:include] = @includes.join(',') unless @includes.empty?
829
- q[:keys] = @keys.join(',') unless @keys.empty?
830
- q[:order] = @order.join(',') unless @order.empty?
863
+ q[:include] = @includes.join(",") unless @includes.empty?
864
+ q[:keys] = @keys.join(",") unless @keys.empty?
865
+ q[:order] = @order.join(",") unless @order.empty?
831
866
  unless @where.empty?
832
867
  q[:where] = Parse::Query.compile_where(@where)
833
868
  q[:where] = q[:where].to_json if encode
@@ -847,15 +882,13 @@ module Parse
847
882
 
848
883
  # @return [Hash] a hash representing just the `where` clause of this query.
849
884
  def compile_where
850
- self.class.compile_where( @where || [] )
885
+ self.class.compile_where(@where || [])
851
886
  end
852
887
 
853
888
  # Retruns a formatted JSON string representing the query, useful for debugging.
854
889
  # @return [String]
855
890
  def pretty
856
- JSON.pretty_generate( as_json )
891
+ JSON.pretty_generate(as_json)
857
892
  end
858
-
859
893
  end # Query
860
-
861
894
  end # Parse
@@ -1,9 +1,9 @@
1
1
  # encoding: UTF-8
2
2
  # frozen_string_literal: true
3
3
 
4
- require_relative 'operation'
5
- require 'time'
6
- require 'date'
4
+ require_relative "operation"
5
+ require "time"
6
+ require "date"
7
7
 
8
8
  module Parse
9
9
  # Constraints are the heart of the Parse::Query system.
@@ -39,12 +39,11 @@ module Parse
39
39
  # it most likely is just the field name, so let's assume they want
40
40
  # the default equality operation.
41
41
  if operation.is_a?(Operation) == false && operation.respond_to?(:to_sym)
42
- operation = Operation.new(operation.to_sym, self.class.operand)
42
+ operation = Operation.new(operation.to_sym, self.class.operand)
43
43
  end
44
44
  @operation = operation
45
45
  @value = value
46
46
  yield(self) if block_given?
47
-
48
47
  end
49
48
 
50
49
  class << self
@@ -122,7 +121,6 @@ module Parse
122
121
  end
123
122
  d
124
123
  end
125
-
126
124
  end
127
125
 
128
126
  # @return [Integer] the precedence of this constraint
@@ -1,7 +1,7 @@
1
1
  # encoding: UTF-8
2
2
  # frozen_string_literal: true
3
3
 
4
- require_relative 'constraint'
4
+ require_relative "constraint"
5
5
 
6
6
  # Each constraint type is a subclass of Parse::Constraint
7
7
  # We register each keyword (which is the Parse query operator)
@@ -60,7 +60,7 @@ module Parse
60
60
  value = formatted_value
61
61
  # if it is already a pointer value, just return the constraint. Allows for
62
62
  # supporting strings, symbols and pointers.
63
- return { @operation.operand => value } if value.is_a?(Parse::Pointer)
63
+ return { @operation.operand => value } if value.is_a?(Parse::Pointer)
64
64
 
65
65
  begin
66
66
  klass = className.constantize
@@ -79,9 +79,8 @@ module Parse
79
79
  raise ArgumentError, "#{self.class}: value must be of string type representing a Parse object id."
80
80
  end
81
81
  value.strip!
82
- return { @operation.operand => klass.pointer(value) }
82
+ return { @operation.operand => klass.pointer(value) }
83
83
  end
84
-
85
84
  end
86
85
 
87
86
  # Equivalent to the `$or` Parse query operation. This is useful if you want to
@@ -101,7 +100,6 @@ module Parse
101
100
  or_clauses = formatted_value
102
101
  return { :$or => Array.wrap(or_clauses) }
103
102
  end
104
-
105
103
  end
106
104
 
107
105
  # Equivalent to the `$lte` Parse query operation. The alias `on_or_before` is provided for readability.
@@ -154,6 +152,7 @@ module Parse
154
152
  register :less_than
155
153
  register :before
156
154
  end
155
+
157
156
  # Equivalent to the `$gt` Parse query operation. The alias `after` is provided for readability.
158
157
  # q.where :field.gt => value
159
158
  # q.where :field.after => date
@@ -252,13 +251,12 @@ module Parse
252
251
  end
253
252
 
254
253
  if value == true
255
- return { @operation.operand => { key => false} }
254
+ return { @operation.operand => { key => false } }
256
255
  else
257
256
  #current bug in parse where if you want exists => true with geo queries
258
257
  # we should map it to a "not equal to null" constraint
259
258
  return { @operation.operand => { Parse::Constraint::NotEqualConstraint.key => nil } }
260
259
  end
261
-
262
260
  end
263
261
  end
264
262
 
@@ -319,7 +317,6 @@ module Parse
319
317
  val = [val].compact unless val.is_a?(Array)
320
318
  { @operation.operand => { key => val } }
321
319
  end
322
-
323
320
  end
324
321
 
325
322
  # Equivalent to the `$nin` Parse query operation. Checks whether the value in
@@ -357,7 +354,6 @@ module Parse
357
354
  val = [val].compact unless val.is_a?(Array)
358
355
  { @operation.operand => { key => val } }
359
356
  end
360
-
361
357
  end
362
358
 
363
359
  # Equivalent to the $all Parse query operation. Checks whether the value in
@@ -585,7 +581,6 @@ module Parse
585
581
  contraint_keyword :$notInQuery
586
582
  register :excludes
587
583
  register :not_in_query
588
-
589
584
  end
590
585
 
591
586
  # Equivalent to the `$nearSphere` Parse query operation. This is only applicable
@@ -631,7 +626,6 @@ module Parse
631
626
  end
632
627
  { @operation.operand => { key => point } }
633
628
  end
634
-
635
629
  end
636
630
 
637
631
  # Equivalent to the `$within` Parse query operation and `$box` geopoint
@@ -661,10 +655,10 @@ module Parse
661
655
  def build
662
656
  geopoint_values = formatted_value
663
657
  unless geopoint_values.is_a?(Array) && geopoint_values.count == 2 &&
664
- geopoint_values.first.is_a?(Parse::GeoPoint) && geopoint_values.last.is_a?(Parse::GeoPoint)
665
- raise(ArgumentError, '[Parse::Query] Invalid query value parameter passed to `within_box` constraint. ' +
666
- 'Values in array must be `Parse::GeoPoint` objects and ' +
667
- 'it should be in an array format: [southwestPoint, northeastPoint]' )
658
+ geopoint_values.first.is_a?(Parse::GeoPoint) && geopoint_values.last.is_a?(Parse::GeoPoint)
659
+ raise(ArgumentError, "[Parse::Query] Invalid query value parameter passed to `within_box` constraint. " +
660
+ "Values in array must be `Parse::GeoPoint` objects and " +
661
+ "it should be in an array format: [southwestPoint, northeastPoint]")
668
662
  end
669
663
  { @operation.operand => { :$within => { :$box => geopoint_values } } }
670
664
  end
@@ -703,17 +697,65 @@ module Parse
703
697
  def build
704
698
  geopoint_values = formatted_value
705
699
  unless geopoint_values.is_a?(Array) &&
706
- geopoint_values.all? {|point| point.is_a?(Parse::GeoPoint) } &&
700
+ geopoint_values.all? { |point| point.is_a?(Parse::GeoPoint) } &&
707
701
  geopoint_values.count > 2
708
- raise ArgumentError, '[Parse::Query] Invalid query value parameter passed to'\
709
- ' `within_polygon` constraint: Value must be an array with 3'\
710
- ' or more `Parse::GeoPoint` objects'
702
+ raise ArgumentError, "[Parse::Query] Invalid query value parameter passed to" \
703
+ " `within_polygon` constraint: Value must be an array with 3" \
704
+ " or more `Parse::GeoPoint` objects"
711
705
  end
712
706
 
713
707
  { @operation.operand => { :$geoWithin => { :$polygon => geopoint_values } } }
714
708
  end
715
709
  end
716
710
 
717
- end
711
+ # Equivalent to the full text search support with `$text` with a set of search crieteria.
712
+ class FullTextSearchQueryConstraint < Constraint
713
+ # @!method text_search
714
+ # A registered method on a symbol to create the constraint. Maps to Parse
715
+ # operator "$text" with "$search" subconstraint. Takes a hash of parameters.
716
+ # @example
717
+ # # As many points as you want
718
+ # q.where :field.text_search => {parameters}
719
+ #
720
+ # Where `parameters` can be one of:
721
+ # $term : Specify a field to search (Required)
722
+ # $language : Determines the list of stop words and the rules for tokenizer.
723
+ # $caseSensitive : Enable or disable case sensitive search.
724
+ # $diacriticSensitive : Enable or disable diacritic sensitive search
725
+ #
726
+ # @note This method will automatically add `$` to each key of the parameters
727
+ # hash if it doesn't already have it.
728
+ # @return [WithinPolygonQueryConstraint]
729
+ # @version 1.8.0 (requires Server v2.5.0 or later)
730
+ contraint_keyword :$text
731
+ register :text_search
718
732
 
733
+ # @return [Hash] the compiled constraint.
734
+ def build
735
+ params = formatted_value
736
+
737
+ params = { :$term => params.to_s } if params.is_a?(String) || params.is_a?(Symbol)
738
+
739
+ unless params.is_a?(Hash)
740
+ raise ArgumentError, "[Parse::Query] Invalid query value parameter passed to" \
741
+ " `text_search` constraint: Value must be a string or a hash of parameters."
742
+ end
743
+
744
+ params = params.inject({}) do |h, (k, v)|
745
+ u = k.to_s
746
+ u = u.columnize.prepend("$") unless u.start_with?("$")
747
+ h[u] = v
748
+ h
749
+ end
750
+
751
+ unless params["$term"].present?
752
+ raise ArgumentError, "[Parse::Query] Invalid query value parameter passed to" \
753
+ " `text_search` constraint: Missing required `$term` subkey.\n" \
754
+ "\tExample: #{@operation.operand}.text_search => { term: 'text to search' }"
755
+ end
756
+
757
+ { @operation.operand => { :$text => { :$search => params } } }
758
+ end
759
+ end
760
+ end
719
761
  end