rao-query 0.0.3.pre
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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +28 -0
- data/Rakefile +25 -0
- data/app/concerns/rao/query/controller/query_concern.rb +70 -0
- data/app/concerns/rao/query/controller/query_form_concern.rb~ +13 -0
- data/app/parsers/rao/query/condition_parser.rb +149 -0
- data/app/view_helpers/rao/query/application_helper.rb +131 -0
- data/lib/rao/query/configuration.rb +9 -0
- data/lib/rao/query/engine.rb +7 -0
- data/lib/rao/query/version.rb +7 -0
- data/lib/rao/query.rb +11 -0
- data/lib/rao-query.rb +1 -0
- metadata +168 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 19dcce90ee295149c4a55e9412bbcf3ecf98407d
|
4
|
+
data.tar.gz: 28f11c998767d9f7304e52793af3739638701ea5
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 064ab43e5fd6708d42008df4eb0f46b5f2fbb341104b94c16646818f4d9ba1dfeeb9c4c01407dfcca846d65a29ed71dbbd5e598348c3667e63e354a0c3c15407
|
7
|
+
data.tar.gz: 83f3bf5075cf12df8af694c39dd774ac0d1787f1d17efa725afc62dc610e055509e9a95aaa15e3370386bee3d4a780c98c1f31dc9489a6f99a934238625b0f92
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2018 Roberto Vasquez Angel
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# Rails Add-Ons Query
|
2
|
+
Short description and motivation.
|
3
|
+
|
4
|
+
## Usage
|
5
|
+
How to use my plugin.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
Add this line to your application's Gemfile:
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
gem 'rao-query'
|
12
|
+
```
|
13
|
+
|
14
|
+
And then execute:
|
15
|
+
```bash
|
16
|
+
$ bundle
|
17
|
+
```
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
```bash
|
21
|
+
$ gem install rao-query
|
22
|
+
```
|
23
|
+
|
24
|
+
## Contributing
|
25
|
+
Contribution directions go here.
|
26
|
+
|
27
|
+
## License
|
28
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rdoc/task'
|
8
|
+
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'Rails Add-Ons Query'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('README.md')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
|
18
|
+
load 'rails/tasks/engine.rake'
|
19
|
+
|
20
|
+
|
21
|
+
load 'rails/tasks/statistics.rake'
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
require 'bundler/gem_tasks'
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module Rao
|
2
|
+
module Query
|
3
|
+
module Controller
|
4
|
+
# Example
|
5
|
+
#
|
6
|
+
# # app/controllers/posts_controller.rb
|
7
|
+
# class PostsController < ApplicationController
|
8
|
+
# include Rao::Query::Controller::QueryConcern
|
9
|
+
#
|
10
|
+
# def index
|
11
|
+
# @posts = with_conditions_from_query(Post).all
|
12
|
+
# end
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
module QueryConcern
|
16
|
+
extend ActiveSupport::Concern
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def with_conditions_from_query(scope)
|
21
|
+
if query_params.keys.include?('q')
|
22
|
+
condition_params = normalize_query_params(query_params)
|
23
|
+
else
|
24
|
+
condition_params = query_params
|
25
|
+
end
|
26
|
+
|
27
|
+
condition_params.reject.reject { |k,v| v.blank? }.each do |field, condition|
|
28
|
+
case field
|
29
|
+
when 'limit'
|
30
|
+
scope = scope.limit(condition.to_i)
|
31
|
+
when 'offset'
|
32
|
+
scope = scope.offset(condition.to_i)
|
33
|
+
when 'order'
|
34
|
+
scope = scope.order(condition)
|
35
|
+
when 'includes'
|
36
|
+
scope = scope.includes(condition.map(&:to_sym))
|
37
|
+
else
|
38
|
+
condition_statement = ::Rao::Query::ConditionParser.new(scope, field, condition).condition_statement
|
39
|
+
scope = scope.where(condition_statement)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
scope
|
43
|
+
end
|
44
|
+
|
45
|
+
def query_params
|
46
|
+
default_query_params
|
47
|
+
end
|
48
|
+
|
49
|
+
def default_query_params
|
50
|
+
request.query_parameters.except(*default_query_params_exceptions)
|
51
|
+
end
|
52
|
+
|
53
|
+
def default_query_params_exceptions
|
54
|
+
%w(sort_by sort_direction utf8 commit page)
|
55
|
+
end
|
56
|
+
|
57
|
+
def normalize_query_params(params)
|
58
|
+
params['q'].each_with_object({}) { |(k, v), m| m[normalize_key(k)] = v }
|
59
|
+
end
|
60
|
+
|
61
|
+
def normalize_key(key)
|
62
|
+
splitted_key = key.split('_')
|
63
|
+
predicate = splitted_key.last
|
64
|
+
attribute = splitted_key[0..-2].join('_')
|
65
|
+
"#{attribute}(#{predicate})"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
module Rao
|
2
|
+
module Query
|
3
|
+
class ConditionParser
|
4
|
+
OPERATOR_MAP = {
|
5
|
+
gt: :>,
|
6
|
+
gt_or_eq: :>=,
|
7
|
+
eq: :'=',
|
8
|
+
not_eq: :'<>',
|
9
|
+
lt_or_eq: :<=,
|
10
|
+
lt: :<,
|
11
|
+
null: :is_null,
|
12
|
+
not_null: :is_not_null,
|
13
|
+
cont: :like
|
14
|
+
}
|
15
|
+
|
16
|
+
def initialize(scope, field, condition)
|
17
|
+
@scope, @field, @condition = scope, field, condition
|
18
|
+
end
|
19
|
+
|
20
|
+
def condition_statement
|
21
|
+
build_condition_statement(@field, @condition)
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def build_condition_statement(parent_key, condition, nested = false)
|
27
|
+
if is_a_condition?(parent_key) && !nested
|
28
|
+
table, column, operator = extract_table_column_and_operator(parent_key)
|
29
|
+
return handle_null_condition(column, operator) if is_null_operator?(operator)
|
30
|
+
# binding.pry
|
31
|
+
if operator == 'cont'
|
32
|
+
return ["#{table}.#{column} LIKE ?", "%#{normalized_condition(table, column, condition)}%"]
|
33
|
+
else
|
34
|
+
return ["#{table}.#{column} = ?", normalized_condition(table, column, condition)]
|
35
|
+
end
|
36
|
+
# if column_is_boolean?(column)
|
37
|
+
# ["#{column} = ?", to_boolean(condition)]
|
38
|
+
# else
|
39
|
+
# ["#{column} = ?", condition]
|
40
|
+
# end
|
41
|
+
else
|
42
|
+
if nested
|
43
|
+
column = extract_column(parent_key)
|
44
|
+
{ column => condition }
|
45
|
+
else
|
46
|
+
{ parent_key => build_condition_statement(condition.first[0], condition.first[1], true) }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def is_null_operator?(operator)
|
52
|
+
%w(null not_null).include?(operator)
|
53
|
+
end
|
54
|
+
|
55
|
+
def handle_null_condition(column, operator)
|
56
|
+
case operator.to_sym
|
57
|
+
when :null
|
58
|
+
"#{column} IS NULL"
|
59
|
+
when :not_null
|
60
|
+
"#{column} IS NOT NULL"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def is_a_condition?(obj)
|
65
|
+
!!extract_operator(obj)
|
66
|
+
end
|
67
|
+
|
68
|
+
def extract_operator(obj)
|
69
|
+
string = obj.to_s
|
70
|
+
operator_map.each do |key, value|
|
71
|
+
return value if string.end_with?("(#{key})")
|
72
|
+
end
|
73
|
+
nil
|
74
|
+
end
|
75
|
+
|
76
|
+
def extract_column(obj)
|
77
|
+
obj.to_s.split("(").first
|
78
|
+
end
|
79
|
+
|
80
|
+
# def extract_column_and_operator(string)
|
81
|
+
# if string =~ /([\.a-z_]{1,})\(([a-z_]{2,})\)/
|
82
|
+
# return $~[1], $~[2]
|
83
|
+
# end
|
84
|
+
# end
|
85
|
+
|
86
|
+
def extract_table_column_and_operator(string)
|
87
|
+
if string =~ /([\.a-z_]{1,})\(([a-z_]{2,})\)/
|
88
|
+
table_and_column = $~[1]
|
89
|
+
operator = $~[2]
|
90
|
+
column, table_or_association = table_and_column.split('.').reverse
|
91
|
+
if table_or_association.nil?
|
92
|
+
table = @scope.table_name
|
93
|
+
else
|
94
|
+
table = tables_and_classes_with_associations[table_or_association].table_name
|
95
|
+
end
|
96
|
+
return table, column, operator
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def operator_map
|
101
|
+
OPERATOR_MAP
|
102
|
+
end
|
103
|
+
|
104
|
+
def column_is_boolean?(table_name, column_name)
|
105
|
+
scope, column = get_scope_and_column_from_column_name(column_name, table_name)
|
106
|
+
raise "Unknown column: #{column_name}" unless scope.columns_hash.has_key?(column)
|
107
|
+
scope.columns_hash[column].type == :boolean
|
108
|
+
end
|
109
|
+
|
110
|
+
def get_scope_and_column_from_column_name(column_name, table_name = nil)
|
111
|
+
if table_name == @scope.table_name
|
112
|
+
return @scope, column_name
|
113
|
+
else
|
114
|
+
# tables_and_classes = @scope.reflect_on_all_associations.reject { |a| a.polymorphic? }.each_with_object({}) { |a, memo| memo[a.table_name] = a.klass }
|
115
|
+
# associations_and_classes = @scope.reflect_on_all_associations.reject { |a| a.polymorphic? }.each_with_object({}) { |a, memo| memo[a.name.to_s] = a.klass }
|
116
|
+
# scope = tables_and_classes.merge(associations_and_classes)[$~[1]]
|
117
|
+
scope = tables_and_classes_with_associations[table_name]
|
118
|
+
return scope, column_name
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def tables_and_classes_with_associations
|
123
|
+
tables_and_classes = @scope.reflect_on_all_associations.reject { |a| (a.respond_to?(:polymorphic?) && a.polymorphic?) || a.options[:polymorphic] == true }.each_with_object({}) { |a, memo| memo[a.table_name] = a.klass }
|
124
|
+
associations_and_classes = @scope.reflect_on_all_associations.reject { |a| (a.respond_to?(:polymorphic?) && a.polymorphic?) || a.options[:polymorphic] == true }.each_with_object({}) { |a, memo| memo[a.name.to_s] = a.klass }
|
125
|
+
tables_and_classes.merge(associations_and_classes)
|
126
|
+
end
|
127
|
+
|
128
|
+
def to_boolean(string)
|
129
|
+
result = case
|
130
|
+
when Rails.version < '4.2'
|
131
|
+
::ActiveRecord::ConnectionAdapters::Column.value_to_boolean(string)
|
132
|
+
when Rails.version < '5.0'
|
133
|
+
::ActiveRecord::Type::Boolean.new.type_cast_for_schema(string)
|
134
|
+
else
|
135
|
+
::ActiveRecord::Type::Boolean.new.cast(string)
|
136
|
+
end
|
137
|
+
result.gsub('"', '')
|
138
|
+
end
|
139
|
+
|
140
|
+
def normalized_condition(table, column, condition)
|
141
|
+
if column_is_boolean?(table, column)
|
142
|
+
to_boolean(condition)
|
143
|
+
else
|
144
|
+
condition
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
module Rao
|
2
|
+
module Query
|
3
|
+
# First you have to add the helper and the query concern to your controller:
|
4
|
+
#
|
5
|
+
# # app/controllers/application_controller.rb
|
6
|
+
# class ApplicationController < ActionController::Base
|
7
|
+
# include Rao::Query::Controller::QueryConcern
|
8
|
+
# view_helper Rao::Query::ApplicationHelper, as: :query_helper
|
9
|
+
# # ....
|
10
|
+
# end
|
11
|
+
#
|
12
|
+
class ApplicationHelper < ViewHelper::Base
|
13
|
+
# Example:
|
14
|
+
#
|
15
|
+
# # app/views/posts/index.html.haml
|
16
|
+
# = query_helper(self).form_for(@posts, url: posts_path, method: :get) do |f|
|
17
|
+
# = f.input :title_cont
|
18
|
+
# = f.input :body_cont
|
19
|
+
# = f.boolean :published_eq
|
20
|
+
# = f.submit nil, class: 'btn btn-primary'
|
21
|
+
# = f.reset nil, class: 'btn btn-default'
|
22
|
+
#
|
23
|
+
# # app/controllers/posts_controller.rb
|
24
|
+
# class ApplicationController < ActionController::Base
|
25
|
+
# def index
|
26
|
+
# @posts = with_conditions_from_query(Post).all
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# If you are using bootstrap you may want to display the form inline for a
|
30
|
+
# more compact view:
|
31
|
+
#
|
32
|
+
# = query_helper(self).form_for(collection, html: { class: 'form-inline' }) do |f|
|
33
|
+
#
|
34
|
+
def form_for(collection, options = {}, &block)
|
35
|
+
handle_simple_form_missing unless c.respond_to?(:simple_form_for)
|
36
|
+
wrapped_collection = SearchableCollection.new(collection, c.params[:q])
|
37
|
+
c.simple_form_for(wrapped_collection, options.reverse_merge(as: :q, url: c.collection_path, method: :get, builder: SearchFormBuilder), &block)
|
38
|
+
end
|
39
|
+
|
40
|
+
class SearchFormBuilder < SimpleForm::FormBuilder
|
41
|
+
def boolean(name, options = {})
|
42
|
+
translated_label = translate_label_for_boolean(name)
|
43
|
+
options.reverse_merge!(collection: [[I18n.t("search_form_builder.yes"), 1], [I18n.t("search_form_builder.no"), 0]], include_blank: true, label: translated_label)
|
44
|
+
input name, options
|
45
|
+
end
|
46
|
+
|
47
|
+
def input(name, options = {})
|
48
|
+
if association = options.delete(:association)
|
49
|
+
translated_label = translate_label(name, association)
|
50
|
+
input_name = "#{association}.#{name}"
|
51
|
+
else
|
52
|
+
translated_label = translate_label(name)
|
53
|
+
input_name = name
|
54
|
+
end
|
55
|
+
super(input_name, options.reverse_merge(label: translated_label))
|
56
|
+
end
|
57
|
+
|
58
|
+
def submit(title = nil, options = {})
|
59
|
+
title ||= I18n.t('search_form_builder.submit')
|
60
|
+
super(title, options)
|
61
|
+
end
|
62
|
+
|
63
|
+
def reset(title = nil, options = {})
|
64
|
+
title ||= I18n.t('search_form_builder.reset')
|
65
|
+
link_html = options.delete(:link_html) || {}
|
66
|
+
template.link_to(title, template.url_for(), link_html)
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def translate_label(name, association = nil)
|
72
|
+
splitted_name = name.to_s.split('_')
|
73
|
+
attribute_name = splitted_name[0..-2].join('_')
|
74
|
+
predicate = splitted_name.last
|
75
|
+
translated_attribute_name = if association.nil?
|
76
|
+
klass_name = object.original_model_class_name
|
77
|
+
klass_name.constantize.human_attribute_name(attribute_name)
|
78
|
+
else
|
79
|
+
klass_name = object.original_model_class.reflect_on_association(association).klass.name
|
80
|
+
klass = klass_name.constantize
|
81
|
+
"#{klass.model_name.human} #{klass.human_attribute_name(attribute_name)}"
|
82
|
+
end
|
83
|
+
I18n.t("search_form_builder.predicates.#{predicate}", attribute_name: translated_attribute_name)
|
84
|
+
end
|
85
|
+
|
86
|
+
def translate_label_for_boolean(name)
|
87
|
+
splitted_name = name.to_s.split('_')
|
88
|
+
attribute_name = splitted_name[0..-2].join('_')
|
89
|
+
predicate = splitted_name.last
|
90
|
+
if association.nil?
|
91
|
+
klass_name = object.original_model_class_name
|
92
|
+
else
|
93
|
+
klass_name = object.original_model_class.reflect_on_association(association).klass
|
94
|
+
end
|
95
|
+
translated_attribute_name = klass_name.constantize.human_attribute_name(attribute_name)
|
96
|
+
I18n.t("search_form_builder.boolean_label", attribute_name: translated_attribute_name)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
class SearchableCollection
|
101
|
+
include ActiveModel::Model
|
102
|
+
extend ActiveModel::Translation
|
103
|
+
|
104
|
+
def method_missing(method, *args)
|
105
|
+
if method.to_s.match(/(.+)_(gt|gt_or_eq|eq|not_eq|lt_or_eq|lt|null|not_null|cont)/)
|
106
|
+
@query.send(:[], method)
|
107
|
+
else
|
108
|
+
super
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def initialize(collection, query)
|
113
|
+
@collection = collection
|
114
|
+
@query = query || {}
|
115
|
+
end
|
116
|
+
|
117
|
+
def original_model_class_name
|
118
|
+
@collection.class.to_s.deconstantize
|
119
|
+
end
|
120
|
+
|
121
|
+
def original_model_class
|
122
|
+
@collection.klass
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def handle_simple_form_missing
|
127
|
+
raise "simple_form_for is not available. Please add simple_form to your Gemfile."
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
data/lib/rao/query.rb
ADDED
data/lib/rao-query.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'rao/query'
|
metadata
ADDED
@@ -0,0 +1,168 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rao-query
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.3.pre
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Roberto Vasquez Angel
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-12-20 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rao
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rao-view_helper
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: sqlite3
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec-rails
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: guard-rspec
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: guard-bundler
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: pry
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
description:
|
126
|
+
email:
|
127
|
+
- roberto@vasquez-angel.de
|
128
|
+
executables: []
|
129
|
+
extensions: []
|
130
|
+
extra_rdoc_files: []
|
131
|
+
files:
|
132
|
+
- MIT-LICENSE
|
133
|
+
- README.md
|
134
|
+
- Rakefile
|
135
|
+
- app/concerns/rao/query/controller/query_concern.rb
|
136
|
+
- app/concerns/rao/query/controller/query_form_concern.rb~
|
137
|
+
- app/parsers/rao/query/condition_parser.rb
|
138
|
+
- app/view_helpers/rao/query/application_helper.rb
|
139
|
+
- lib/rao-query.rb
|
140
|
+
- lib/rao/query.rb
|
141
|
+
- lib/rao/query/configuration.rb
|
142
|
+
- lib/rao/query/engine.rb
|
143
|
+
- lib/rao/query/version.rb
|
144
|
+
homepage: https://github.com/rao
|
145
|
+
licenses:
|
146
|
+
- MIT
|
147
|
+
metadata: {}
|
148
|
+
post_install_message:
|
149
|
+
rdoc_options: []
|
150
|
+
require_paths:
|
151
|
+
- lib
|
152
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
153
|
+
requirements:
|
154
|
+
- - ">="
|
155
|
+
- !ruby/object:Gem::Version
|
156
|
+
version: '0'
|
157
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
158
|
+
requirements:
|
159
|
+
- - ">"
|
160
|
+
- !ruby/object:Gem::Version
|
161
|
+
version: 1.3.1
|
162
|
+
requirements: []
|
163
|
+
rubyforge_project:
|
164
|
+
rubygems_version: 2.6.14
|
165
|
+
signing_key:
|
166
|
+
specification_version: 4
|
167
|
+
summary: Simple Filter Queries for Ruby on Rails.
|
168
|
+
test_files: []
|