parse-stack 1.7.3 → 1.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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