ransack 2.0.1 → 2.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1e44db6020449735b694bd18943195f6e7cdd3597a8dc776d22a54114b4b9273
4
- data.tar.gz: cdcb6ef8b863873fcaa7c2067cb20636c4e856e27f431488978201a310023f45
3
+ metadata.gz: c2eab955e89328399bcb163a575725ea51969653edb1edd66773b6f60554fd12
4
+ data.tar.gz: 1e6d34f5d87238a18c7ae2194cd0d5320d9460b97b8d8c30ec79d82de6aa139a
5
5
  SHA512:
6
- metadata.gz: ded22ffb680b2a358ee72ab348b8f9debc7f2c927c878ec5a4ad872b552b715e561e9b0aac188d874c67cce70f6463d62b3be7655e46900a706214d58d69fa88
7
- data.tar.gz: 6f45114a54ef6f83cbd99780ba432069cf4111c4b9d2294141f238526655edc1cb035422705565389e4c60f75666716d8fd201887f7ca9fd90c92314bbb3b9e6
6
+ metadata.gz: 52c4a46725d9bb474fbb229c39d9638c730d77bd53211f00f639b78690fcd72aaaa2418b56704c30024c36c39ca7cebde0e86b76cba13704a26f4416791ad141
7
+ data.tar.gz: bd6880992a977511ea37df47d0828e8ee1e855dff39e2620eaed89bc043ffde2960e3006ebcc0609c9738af10faea6947a1db1f91f1f3eebc65b631d97137054
data/.gitignore CHANGED
@@ -3,3 +3,4 @@
3
3
  Gemfile.lock
4
4
  pkg/*
5
5
  coverage/*
6
+ .DS_Store
data/.travis.yml CHANGED
@@ -4,7 +4,6 @@ sudo: false
4
4
 
5
5
  rvm:
6
6
  - 2.5
7
- - 2.2
8
7
 
9
8
  env:
10
9
  - RAILS=5-2-stable DB=sqlite3
@@ -23,10 +22,6 @@ env:
23
22
  - RAILS=5-1-stable DB=mysql
24
23
  - RAILS=5-1-stable DB=postgres
25
24
 
26
- - RAILS=5-0-stable DB=sqlite3
27
- - RAILS=5-0-stable DB=mysql
28
- - RAILS=5-0-stable DB=postgres
29
-
30
25
  matrix:
31
26
  allow_failures:
32
27
  - env: RAILS=5-2-stable DB=sqlite3
data/CHANGELOG.md CHANGED
@@ -2,6 +2,57 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## Version 2.1.1 - 2018-12-05
6
+
7
+ * Add `arabic` translation
8
+ https://github.com/activerecord-hackery/ransack/pull/979
9
+
10
+ * Deprecate #search
11
+ PR [975](https://github.com/activerecord-hackery/ransack/pull/975)
12
+
13
+ ## Version 2.1.0 - 2018-10-26
14
+
15
+ * Add support for sorting by scopes
16
+ PR [973](https://github.com/activerecord-hackery/ransack/pull/973)
17
+
18
+ *Diego Borges*
19
+
20
+ * Added a new logo for Ransack
21
+ PR [972](https://github.com/activerecord-hackery/ransack/pull/972)
22
+
23
+ *Anıl Kılıç*, *Greg Molnar*
24
+
25
+ * Greek translations
26
+ PR [971](https://github.com/activerecord-hackery/ransack/pull/971)
27
+ PR [960](https://github.com/activerecord-hackery/ransack/pull/960)
28
+
29
+ *Sean Carroll*, *Greg Molnar*
30
+
31
+ * README improvements
32
+ PR [963](https://github.com/activerecord-hackery/ransack/pull/963)
33
+
34
+ *tommaso1*
35
+
36
+ * Bulgarian translations
37
+ PR [961](https://github.com/activerecord-hackery/ransack/pull/961)
38
+
39
+ *Sean Carroll*
40
+
41
+ * README improvements
42
+ PR [956](https://github.com/activerecord-hackery/ransack/pull/956)
43
+
44
+ *Alex Konoval*
45
+
46
+ * Remove lib/ransack/adapters/active_record/compat.rb
47
+ PR [954](https://github.com/activerecord-hackery/ransack/pull/954)
48
+
49
+ *Ryuta Kamizono*
50
+
51
+ * Remove unused aliases
52
+ PR [953](https://github.com/activerecord-hackery/ransack/pull/953)
53
+
54
+ *Ryuta Kamizono*
55
+
5
56
  ## Version 2.0.1 - 2018-08-18
6
57
 
7
58
  * Don't return association if table is nil
data/README.md CHANGED
@@ -1,15 +1,16 @@
1
- # Ransack
1
+ # ![Ransack](./logo/ransack-h.png "Ransack")
2
2
 
3
3
  [![Build Status](https://travis-ci.org/activerecord-hackery/ransack.svg)](https://travis-ci.org/activerecord-hackery/ransack)
4
4
  [![Gem Version](https://badge.fury.io/rb/ransack.svg)](http://badge.fury.io/rb/ransack)
5
5
  [![Code Climate](https://codeclimate.com/github/activerecord-hackery/ransack/badges/gpa.svg)](https://codeclimate.com/github/activerecord-hackery/ransack)
6
+ [![Backers on Open Collective](https://opencollective.com/ransack/backers/badge.svg)](#backers) [![Sponsors on Open Collective](https://opencollective.com/ransack/sponsors/badge.svg)](#sponsors)
6
7
 
7
8
  Ransack is a rewrite of [MetaSearch](https://github.com/activerecord-hackery/meta_search)
8
9
  created by [Ernie Miller](http://twitter.com/erniemiller)
9
10
  and developed/maintained for years by
10
11
  [Jon Atack](http://twitter.com/jonatack) and
11
12
  [Ryan Bigg](http://twitter.com/ryanbigg) with the help of a great group of
12
- [contributors](https://github.com/activerecord-hackery/ransack/graphs/contributors).
13
+ [contributors](https://github.com/activerecord-hackery/ransack/graphs/contributors). Ransack's logo is designed by [Anıl Kılıç](https://github.com/anilkilic).
13
14
  While it supports many of the same features as MetaSearch, its underlying
14
15
  implementation differs greatly from MetaSearch,
15
16
  and backwards compatibility is not a design goal.
@@ -132,6 +133,11 @@ which are defined in
132
133
  <% end %>
133
134
  ```
134
135
 
136
+ The argument of `f.search_field` has to be in this form:
137
+ `attribute_name[_or_attribute_name]..._predicate`
138
+
139
+ where `[_or_another_attribute_name]...` means any repetition of `_or_` plus the name of the attribute.
140
+
135
141
  `cont` (contains) and `start` (starts with) are just two of the available
136
142
  search predicates. See
137
143
  [Constants](https://github.com/activerecord-hackery/ransack/blob/master/lib/ransack/constants.rb)
@@ -196,6 +202,23 @@ This example toggles the sort directions of both fields, by default
196
202
  initially sorting the `last_name` field by ascending order, and the
197
203
  `first_name` field by descending order.
198
204
 
205
+ In the case that you wish to sort by some complex value, such as the result
206
+ of a SQL function, you may do so using scopes. In your model, define scopes
207
+ whose names line up with the name of the virtual field you wish to sort by,
208
+ as so:
209
+
210
+ ```ruby
211
+ class Person < ActiveRecord::Base
212
+ scope :sort_by_reverse_name_asc, lambda { order("REVERSE(name) ASC") }
213
+ scope :sort_by_reverse_name_desc, lambda { order("REVERSE(name) DESC") }
214
+ ...
215
+ ```
216
+
217
+ and you can then sort by this virtual field:
218
+
219
+ ```erb
220
+ <%= sort_link(@q, :reverse_name) %>
221
+ ```
199
222
 
200
223
  The sort link order indicator arrows may be globally customized by setting a
201
224
  `custom_arrows` option in an initializer file like
@@ -483,7 +506,7 @@ avoid returning duplicate rows, even if conditions on a join would otherwise
483
506
  result in some. It generates the same SQL as calling `uniq` on the relation.
484
507
 
485
508
  Please note that for many databases, a sort on an associated table's columns
486
- may result in invalid SQL with `distinct: true` -- in those cases, you will
509
+ may result in invalid SQL with `distinct: true` -- in those cases, you
487
510
  will need to modify the result as needed to allow these queries to work.
488
511
 
489
512
  For example, you could call joins and includes on the result which has the
@@ -722,7 +745,7 @@ Ransack.configure do |c|
722
745
  end
723
746
  ```
724
747
 
725
- To turn this off on a per-scope basis Ransack adds the following method to
748
+ To turn this off on a per-scope basis Ransack adds the following method to
726
749
  `ActiveRecord::Base` that you can redefine to selectively override sanitization:
727
750
 
728
751
  `ransackable_scopes_skip_sanitize_args`
@@ -911,3 +934,32 @@ directly related to bug reports, pull requests, or documentation improvements.
911
934
  * Spread the word on Twitter, Facebook, and elsewhere if Ransack's been useful
912
935
  to you. The more people who are using the project, the quicker we can find and
913
936
  fix bugs!
937
+
938
+ ## Contributors
939
+
940
+ This project exists thanks to all the people who contribute. <img src="https://opencollective.com/ransack/contributors.svg?width=890&button=false" />
941
+
942
+
943
+ ## Backers
944
+
945
+ Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/ransack#backer)]
946
+
947
+ <a href="https://opencollective.com/ransack#backers" target="_blank"><img src="https://opencollective.com/ransack/backers.svg?width=890"></a>
948
+
949
+
950
+ ## Sponsors
951
+
952
+ Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/ransack#sponsor)]
953
+
954
+ <a href="https://opencollective.com/ransack/sponsor/0/website" target="_blank"><img src="https://opencollective.com/ransack/sponsor/0/avatar.svg"></a>
955
+ <a href="https://opencollective.com/ransack/sponsor/1/website" target="_blank"><img src="https://opencollective.com/ransack/sponsor/1/avatar.svg"></a>
956
+ <a href="https://opencollective.com/ransack/sponsor/2/website" target="_blank"><img src="https://opencollective.com/ransack/sponsor/2/avatar.svg"></a>
957
+ <a href="https://opencollective.com/ransack/sponsor/3/website" target="_blank"><img src="https://opencollective.com/ransack/sponsor/3/avatar.svg"></a>
958
+ <a href="https://opencollective.com/ransack/sponsor/4/website" target="_blank"><img src="https://opencollective.com/ransack/sponsor/4/avatar.svg"></a>
959
+ <a href="https://opencollective.com/ransack/sponsor/5/website" target="_blank"><img src="https://opencollective.com/ransack/sponsor/5/avatar.svg"></a>
960
+ <a href="https://opencollective.com/ransack/sponsor/6/website" target="_blank"><img src="https://opencollective.com/ransack/sponsor/6/avatar.svg"></a>
961
+ <a href="https://opencollective.com/ransack/sponsor/7/website" target="_blank"><img src="https://opencollective.com/ransack/sponsor/7/avatar.svg"></a>
962
+ <a href="https://opencollective.com/ransack/sponsor/8/website" target="_blank"><img src="https://opencollective.com/ransack/sponsor/8/avatar.svg"></a>
963
+ <a href="https://opencollective.com/ransack/sponsor/9/website" target="_blank"><img src="https://opencollective.com/ransack/sponsor/9/avatar.svg"></a>
964
+
965
+
data/lib/polyamorous.rb CHANGED
@@ -1,22 +1,10 @@
1
1
  if defined?(::ActiveRecord)
2
2
  module Polyamorous
3
- if defined?(Arel::InnerJoin)
4
- InnerJoin = Arel::InnerJoin
5
- OuterJoin = Arel::OuterJoin
6
- else
7
- InnerJoin = Arel::Nodes::InnerJoin
8
- OuterJoin = Arel::Nodes::OuterJoin
9
- end
3
+ InnerJoin = Arel::Nodes::InnerJoin
4
+ OuterJoin = Arel::Nodes::OuterJoin
10
5
 
11
- if defined?(::ActiveRecord::Associations::JoinDependency)
12
- JoinDependency = ::ActiveRecord::Associations::JoinDependency
13
- JoinAssociation = ::ActiveRecord::Associations::JoinDependency::JoinAssociation
14
- JoinBase = ::ActiveRecord::Associations::JoinDependency::JoinBase
15
- else
16
- JoinDependency = ::ActiveRecord::Associations::ClassMethods::JoinDependency
17
- JoinAssociation = ::ActiveRecord::Associations::ClassMethods::JoinDependency::JoinAssociation
18
- JoinBase = ::ActiveRecord::Associations::ClassMethods::JoinDependency::JoinBase
19
- end
6
+ JoinDependency = ::ActiveRecord::Associations::JoinDependency
7
+ JoinAssociation = ::ActiveRecord::Associations::JoinDependency::JoinAssociation
20
8
  end
21
9
 
22
10
  require 'polyamorous/tree_node'
@@ -24,7 +12,8 @@ if defined?(::ActiveRecord)
24
12
  require 'polyamorous/swapping_reflection_class'
25
13
 
26
14
  ar_version = ::ActiveRecord::VERSION::STRING[0,3]
27
- ar_version = ::ActiveRecord::VERSION::STRING[0,5] if ar_version >= '5.2'
15
+ ar_version = ::ActiveRecord::VERSION::STRING[0,5] if ar_version >= "5.2"
16
+ ar_version = "5.2.1" if ::ActiveRecord::VERSION::STRING >= "5.2.1"
28
17
 
29
18
  %w(join_association join_dependency).each do |file|
30
19
  require "polyamorous/activerecord_#{ar_version}_ruby_2/#{file}"
@@ -33,10 +22,4 @@ if defined?(::ActiveRecord)
33
22
  Polyamorous::JoinDependency.send(:prepend, Polyamorous::JoinDependencyExtensions)
34
23
  Polyamorous::JoinDependency.singleton_class.send(:prepend, Polyamorous::JoinDependencyExtensions::ClassMethods)
35
24
  Polyamorous::JoinAssociation.send(:prepend, Polyamorous::JoinAssociationExtensions)
36
-
37
- Polyamorous::JoinBase.class_eval do
38
- if method_defined?(:active_record)
39
- alias_method :base_klass, :active_record
40
- end
41
- end
42
25
  end
@@ -14,6 +14,7 @@ module Ransack
14
14
  end
15
15
 
16
16
  def ransack(params = {}, options = {})
17
+ ActiveSupport::Deprecation.warn("#search is deprecated and will be removed in 2.3, please use #ransack instead") if __callee__ == :search
17
18
  Search.new(self, params, options)
18
19
  end
19
20
 
@@ -1,5 +1,4 @@
1
1
  require 'ransack/context'
2
- require 'ransack/adapters/active_record/compat'
3
2
  require 'polyamorous'
4
3
 
5
4
  module Ransack
@@ -7,11 +6,6 @@ module Ransack
7
6
  module ActiveRecord
8
7
  class Context < ::Ransack::Context
9
8
 
10
- # Because the AR::Associations namespace is insane
11
- if defined? ::ActiveRecord::Associations::JoinDependency
12
- JoinDependency = ::ActiveRecord::Associations::JoinDependency
13
- end
14
-
15
9
  def initialize(object, options = {})
16
10
  super
17
11
  if ::ActiveRecord::VERSION::STRING < Constants::RAILS_5_2
@@ -37,9 +31,29 @@ module Ransack
37
31
  def evaluate(search, opts = {})
38
32
  viz = Visitor.new
39
33
  relation = @object.where(viz.accept(search.base))
34
+
40
35
  if search.sorts.any?
41
- relation = relation.except(:order).reorder(viz.accept(search.sorts))
36
+ relation = relation.except(:order)
37
+ # Rather than applying all of the search's sorts in one fell swoop,
38
+ # as the original implementation does, we apply one at a time.
39
+ #
40
+ # If the sort (returned by the Visitor above) is a symbol, we know
41
+ # that it represents a scope on the model and we can apply that
42
+ # scope.
43
+ #
44
+ # Otherwise, we fall back to the applying the sort with the "order"
45
+ # method as the original implementation did. Actually the original
46
+ # implementation used "reorder," which was overkill since we already
47
+ # have a clean slate after "relation.except(:order)" above.
48
+ viz.accept(search.sorts).each do |scope_or_sort|
49
+ if scope_or_sort.is_a?(Symbol)
50
+ relation = relation.send(scope_or_sort)
51
+ else
52
+ relation = relation.order(scope_or_sort)
53
+ end
54
+ end
42
55
  end
56
+
43
57
  opts[:distinct] ? relation.distinct : relation
44
58
  end
45
59
 
@@ -235,19 +249,19 @@ module Ransack
235
249
  join_list = join_nodes + convert_join_strings_to_ast(relation.table, string_joins)
236
250
 
237
251
  if ::ActiveRecord::VERSION::STRING < Constants::RAILS_5_2_0
238
- join_dependency = JoinDependency.new(relation.klass, association_joins, join_list)
252
+ join_dependency = Polyamorous::JoinDependency.new(relation.klass, association_joins, join_list)
239
253
  join_nodes.each do |join|
240
254
  join_dependency.send(:alias_tracker).aliases[join.left.name.downcase] = 1
241
255
  end
242
256
  elsif ::ActiveRecord::VERSION::STRING == Constants::RAILS_5_2_0
243
257
  alias_tracker = ::ActiveRecord::Associations::AliasTracker.create(self.klass.connection, relation.table.name, join_list)
244
- join_dependency = JoinDependency.new(relation.klass, relation.table, association_joins, alias_tracker)
258
+ join_dependency = Polyamorous::JoinDependency.new(relation.klass, relation.table, association_joins, alias_tracker)
245
259
  join_nodes.each do |join|
246
260
  join_dependency.send(:alias_tracker).aliases[join.left.name.downcase] = 1
247
261
  end
248
262
  else
249
263
  alias_tracker = ::ActiveRecord::Associations::AliasTracker.create(self.klass.connection, relation.table.name, join_list)
250
- join_dependency = JoinDependency.new(relation.klass, relation.table, association_joins)
264
+ join_dependency = Polyamorous::JoinDependency.new(relation.klass, relation.table, association_joins)
251
265
  join_dependency.instance_variable_set(:@alias_tracker, alias_tracker)
252
266
  join_nodes.each do |join|
253
267
  join_dependency.send(:alias_tracker).aliases[join.left.name.downcase] = 1
@@ -276,7 +290,7 @@ module Ransack
276
290
 
277
291
  def build_association(name, parent = @base, klass = nil)
278
292
  if ::ActiveRecord::VERSION::STRING < Constants::RAILS_5_2_0
279
- jd = JoinDependency.new(
293
+ jd = Polyamorous::JoinDependency.new(
280
294
  parent.base_klass,
281
295
  Polyamorous::Join.new(name, @join_type, klass),
282
296
  []
@@ -284,7 +298,7 @@ module Ransack
284
298
  found_association = jd.join_root.children.last
285
299
  elsif ::ActiveRecord::VERSION::STRING == Constants::RAILS_5_2_0
286
300
  alias_tracker = ::ActiveRecord::Associations::AliasTracker.create(self.klass.connection, parent.table.name, [])
287
- jd = JoinDependency.new(
301
+ jd = Polyamorous::JoinDependency.new(
288
302
  parent.base_klass,
289
303
  parent.base_klass.arel_table,
290
304
  Polyamorous::Join.new(name, @join_type, klass),
@@ -292,7 +306,7 @@ module Ransack
292
306
  )
293
307
  found_association = jd.instance_variable_get(:@join_root).children.last
294
308
  else
295
- jd = JoinDependency.new(
309
+ jd = Polyamorous::JoinDependency.new(
296
310
  parent.base_klass,
297
311
  parent.base_klass.arel_table,
298
312
  Polyamorous::Join.new(name, @join_type, klass),
@@ -21,11 +21,15 @@ module Ransack
21
21
  end
22
22
 
23
23
  def visit_Ransack_Nodes_Sort(object)
24
- return unless object.valid?
25
- if object.attr.is_a?(Arel::Attributes::Attribute)
26
- object.attr.send(object.dir)
24
+ if object.valid?
25
+ if object.attr.is_a?(Arel::Attributes::Attribute)
26
+ object.attr.send(object.dir)
27
+ else
28
+ ordered(object)
29
+ end
27
30
  else
28
- ordered(object)
31
+ scope_name = :"sort_by_#{object.name}_#{object.dir}"
32
+ scope_name if object.context.object.respond_to?(scope_name)
29
33
  end
30
34
  end
31
35
 
@@ -0,0 +1,70 @@
1
+ ar:
2
+ ransack:
3
+ search: "بحث"
4
+ predicate: "فاعل"
5
+ and: "و"
6
+ or: "أو"
7
+ any: "أيُّ"
8
+ all: "كل"
9
+ combinator: "دالة توافقية"
10
+ attribute: "خاصية"
11
+ value: "قيمة"
12
+ condition: "شرط"
13
+ sort: "ترتيب"
14
+ asc: "تصاعدي"
15
+ desc: "تنازلي"
16
+ predicates:
17
+ eq: "معادل"
18
+ eq_any: "معادل على اﻷقل لواحد"
19
+ eq_all: "معادل للجميع"
20
+ not_eq: "ليس معادلا لـ"
21
+ not_eq_any: "ليس معادلا على اﻷقل لواحد"
22
+ not_eq_all: "ليس معادلا للجميع"
23
+ matches: "موائم"
24
+ matches_any: "موائم لواحد على اﻷقل"
25
+ matches_all: "موائم للجميع"
26
+ does_not_match: "لا يتواءم"
27
+ does_not_match_any: "لا يتواءم مع واحد على اﻷقل"
28
+ does_not_match_all: "لا يتواءم مع الجميع"
29
+ lt: "أصغر من"
30
+ lt_any: "أصغر لواحد على اﻷقل"
31
+ lt_all: "أصغر من الجميع"
32
+ lteq: "أصغر أو مساو لـ"
33
+ lteq_any: "أصغر أو مساو لواحد على اﻷقل"
34
+ lteq_all: "أصغر أو مساو للجميع"
35
+ gt: "أكبر من"
36
+ gt_any: "أكبر من واحد على اﻷقل"
37
+ gt_all: "أكبر من الجميع"
38
+ gteq: "أكبر أو مساو لـ"
39
+ gteq_any: "أكبر أو مساو لواحد على اﻷقل"
40
+ gteq_all: "أكبر أو مساو للجميع"
41
+ in: "متضمن لـ"
42
+ in_any: "متضمن لواحد على اﻷقل"
43
+ in_all: "متضمن للجميع"
44
+ not_in: "غير متضمن"
45
+ not_in_any: "غير متضمن لواحد على اﻷقل"
46
+ not_in_all: "غير متضمن للجميع"
47
+ cont: "محتو"
48
+ cont_any: "محتو لواحد على اﻷقل"
49
+ cont_all: "محتو لجميع"
50
+ not_cont: "غير محتو"
51
+ not_cont_any: "غير محتو لواحد على اﻷقل"
52
+ not_cont_all: "غير محتو للجميع"
53
+ start: "يبدأ بـ"
54
+ start_any: "يبدأ بواحد على اﻷقل"
55
+ start_all: "يبدأ بالجميع"
56
+ not_start: "لا يبدأ بـ"
57
+ not_start_any: "لا يبدأ بواحد على اﻷقل"
58
+ not_start_all: "لا يبدأ بالجميع"
59
+ end: "ينتهي بـ"
60
+ end_any: "ينتهي بواحد على اﻷقل"
61
+ end_all: "ينتهي بالجميع"
62
+ not_end: "لا ينتهي بـ"
63
+ not_end_any: "لا ينتهي بواحد على اﻷقل"
64
+ not_end_all: "لا ينتهي بالجميع"
65
+ 'true': "صحيح"
66
+ 'false': "خطأ"
67
+ present: "مستقبل"
68
+ blank: "فراغ"
69
+ 'null': "عدم"
70
+ not_null: "غير مساو لقيمة عدم"
@@ -0,0 +1,70 @@
1
+ bg:
2
+ ransack:
3
+ search: "търсене"
4
+ predicate: "предикат"
5
+ and: "и"
6
+ or: "или"
7
+ any: "всякакво"
8
+ all: "всички"
9
+ combinator: "комбинатор"
10
+ attribute: "атрибут"
11
+ value: "стойност"
12
+ condition: "условие"
13
+ sort: "сортиране"
14
+ asc: "възходящ"
15
+ desc: "низходящ"
16
+ predicates:
17
+ eq: "се равнява на"
18
+ eq_any: "се равнява на всяко"
19
+ eq_all: "се равнява на всички"
20
+ not_eq: "не е равно на"
21
+ not_eq_any: "не е равно на никое от"
22
+ not_eq_all: "не е равно на всички"
23
+ matches: "съвпада"
24
+ matches_any: "съвпада с някое"
25
+ matches_all: "съвпада с всички"
26
+ does_not_match: "не съвпада"
27
+ does_not_match_any: "не съвпада с никое"
28
+ does_not_match_all: "не съвпада с всички"
29
+ lt: "по-малко от"
30
+ lt_any: "по-малко от някое"
31
+ lt_all: "по-малко от всички"
32
+ lteq: "по-малко или равно на"
33
+ lteq_any: "по-малко или равно на някое"
34
+ lteq_all: "по-малко или равно на всички"
35
+ gt: "по-голямо от"
36
+ gt_any: "по-голямо от всякое"
37
+ gt_all: "по-голямо от всички"
38
+ gteq: "по-голямо или равно на"
39
+ gteq_any: "по-голямо или равно на всякое"
40
+ gteq_all: "по-голямо или равно на всички"
41
+ in: "в"
42
+ in_any: "във всякое"
43
+ in_all: "във всички"
44
+ not_in: "не в"
45
+ not_in_any: "не в никое"
46
+ not_in_all: "не във всички"
47
+ cont: "съдържа"
48
+ cont_any: "съдържа всякое"
49
+ cont_all: "съдържа всички"
50
+ not_cont: "не съдържа"
51
+ not_cont_any: "не съдържа никое"
52
+ not_cont_all: "не съдържа всички"
53
+ start: "започва с"
54
+ start_any: "започва с всякое"
55
+ start_all: "започва с всички"
56
+ not_start: "не започва с"
57
+ not_start_any: "не започва с никое"
58
+ not_start_all: "не започва с всички"
59
+ end: "завършва с"
60
+ end_any: "завършва с всякое"
61
+ end_all: "завършва с всички"
62
+ not_end: "не завършва с"
63
+ not_end_any: "не завършва с никое"
64
+ not_end_all: "не завършва с всички"
65
+ 'true': "истина"
66
+ 'false': "неистина"
67
+ present: "присъства"
68
+ blank: "е празно"
69
+ 'null': "е нула"
70
+ not_null: "не е нула"