deli 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +77 -0
- data/lib/deli.rb +18 -0
- data/lib/deli/adapters.rb +9 -0
- data/lib/deli/adapters/active_record.rb +251 -0
- data/lib/deli/adapters/cassandra.rb +52 -0
- data/lib/deli/adapters/mongoid.rb +180 -0
- data/lib/deli/adapters/neo4j.rb +54 -0
- data/lib/deli/adapters/simple.rb +39 -0
- data/lib/deli/configuration.rb +47 -0
- data/lib/deli/controller.rb +75 -0
- data/lib/deli/helper.rb +61 -0
- data/lib/deli/model.rb +13 -0
- data/lib/deli/pagination.rb +117 -0
- data/lib/deli/param.rb +189 -0
- data/lib/deli/query.rb +133 -0
- data/lib/deli/railtie.rb +14 -0
- data/spec/active_record_spec.rb +358 -0
- data/spec/cassandra_spec.rb +40 -0
- data/spec/mongoid_spec.rb +40 -0
- data/spec/neo4j_spec.rb +40 -0
- data/spec/param_spec.rb +318 -0
- data/spec/spec_helper.rb +33 -0
- data/spec/support/database.rb +69 -0
- data/spec/support/models.rb +27 -0
- metadata +77 -0
@@ -0,0 +1,54 @@
|
|
1
|
+
module Deli
|
2
|
+
module Adapters
|
3
|
+
# @todo
|
4
|
+
# IceCream.find(:all, :condition => {:flavour => 'chocolate'}, :sort => {:name => :asc})
|
5
|
+
# http://neo4j.rubyforge.org/guides/rails3.html
|
6
|
+
module Neo4j
|
7
|
+
class Query < ::Deli::Query
|
8
|
+
def render(params)
|
9
|
+
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class Param < ::Deli::Param
|
14
|
+
def render(value)
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
def render_value(value, operator = nil)
|
19
|
+
value
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class Time < Param
|
24
|
+
include Deli::Param::Time
|
25
|
+
end
|
26
|
+
|
27
|
+
class Date < Time
|
28
|
+
include Deli::Param::Date
|
29
|
+
end
|
30
|
+
|
31
|
+
class String < Param
|
32
|
+
include Deli::Param::String
|
33
|
+
end
|
34
|
+
|
35
|
+
class Number < Param
|
36
|
+
include Deli::Param::Number
|
37
|
+
end
|
38
|
+
|
39
|
+
class Limit < Param
|
40
|
+
include Deli::Param::Limit
|
41
|
+
end
|
42
|
+
|
43
|
+
class Order < Param
|
44
|
+
include Deli::Param::Order
|
45
|
+
|
46
|
+
def render(value)
|
47
|
+
parse(value).map do |item|
|
48
|
+
[render_name(item[:namespace], item[:key]), item[:operators][0] == "+" ? :asc : :desc]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Deli
|
2
|
+
module Adapters
|
3
|
+
module Simple
|
4
|
+
class Query < ::Deli::Query
|
5
|
+
end
|
6
|
+
|
7
|
+
class Param < ::Deli::Param
|
8
|
+
end
|
9
|
+
|
10
|
+
class Time < Param
|
11
|
+
include Deli::Param::Time
|
12
|
+
end
|
13
|
+
|
14
|
+
class Date < Time
|
15
|
+
include Deli::Param::Date
|
16
|
+
end
|
17
|
+
|
18
|
+
class String < Param
|
19
|
+
include Deli::Param::String
|
20
|
+
end
|
21
|
+
|
22
|
+
class Number < Param
|
23
|
+
include Deli::Param::Number
|
24
|
+
end
|
25
|
+
|
26
|
+
class Limit < Param
|
27
|
+
include Deli::Param::Limit
|
28
|
+
end
|
29
|
+
|
30
|
+
class Order < Param
|
31
|
+
include Deli::Param::Order
|
32
|
+
end
|
33
|
+
|
34
|
+
class Offset < Param
|
35
|
+
include Deli::Param::Offset
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Deli
|
2
|
+
class << self
|
3
|
+
def configuration
|
4
|
+
@configuration ||= Deli::Configuration.new
|
5
|
+
end
|
6
|
+
|
7
|
+
def configure(&block)
|
8
|
+
yield configuration
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class Configuration
|
13
|
+
attr_accessor :per_page, :sort_direction, :sort_key, :limit_key, :page_key, :default_adapter, :query_operators
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
@per_page = 20
|
17
|
+
@sort_direction = "ASC"
|
18
|
+
@sort_key = "sort" # or "order", etc.
|
19
|
+
@limit_key = "limit" # or "per_page", etc.
|
20
|
+
@page_key = "page"
|
21
|
+
@separator = "_" # or "-"
|
22
|
+
|
23
|
+
# this is not used, just thinking...
|
24
|
+
# nested relationships as user[location][city]=san+diego
|
25
|
+
@operators = {
|
26
|
+
:gte => ":value..t",
|
27
|
+
:gt => ":value...t",
|
28
|
+
:lte => "t..:value",
|
29
|
+
:lte => "t...:value",
|
30
|
+
:range_inclusive => ":i..:f", # count=0..4
|
31
|
+
:range_exclusive => ":i...:f", # date=2011-08-10...2011-10-03
|
32
|
+
:in => [",", "+OR+"], # tags=ruby,javascript and tags=ruby+OR+javascript
|
33
|
+
:nin => "-", # tags=-ruby,-javascript and tags=ruby+OR+javascript
|
34
|
+
:all => "[:value]", # tags=[ruby,javascript] and tags=ruby+AND+javascript
|
35
|
+
:nil => "[-]", # tags=[-]
|
36
|
+
:not_nil => "[+]", # tags=ruby,[+]
|
37
|
+
:asc => ["+", ""],
|
38
|
+
:desc => "-",
|
39
|
+
:geo => ":lat,:lng,:radius" # geo=20,-50,7
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
def default_adapter
|
44
|
+
@default_adapter ||= :active_record
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module Deli
|
2
|
+
class Controller
|
3
|
+
attr_accessor :params, :model_name
|
4
|
+
# not clean at all, couples the classes, but just added quickly to accomplish it. needs refactoring.
|
5
|
+
|
6
|
+
def initialize(*args, &block)
|
7
|
+
self.model_name = args.shift
|
8
|
+
options = args.extract_options!
|
9
|
+
@params = []
|
10
|
+
@params << param!(:page, :type => :offset) unless options[:page] == false
|
11
|
+
@params << param!(:sort, :type => :order, :default => options[:sort]) unless options[:sort] == false
|
12
|
+
@params << param!(:limit, :type => :limit, :default => options[:limit] || config.per_page) unless options[:limit] == false
|
13
|
+
instance_eval(&block)
|
14
|
+
self
|
15
|
+
end
|
16
|
+
|
17
|
+
def config
|
18
|
+
Deli.configuration
|
19
|
+
end
|
20
|
+
|
21
|
+
# handles the following:
|
22
|
+
#
|
23
|
+
# match :created_at # figures out attribute from table definition
|
24
|
+
# match :created_by # figures out that it's on the 'users' table, and to add the join
|
25
|
+
# match :name, :to => {:vendor => :name} # maps to 'vendors.name' column.
|
26
|
+
# if 'vendor' is polymorphic, it will figure it out from the association reflection.
|
27
|
+
# can only handle one level deep for now, no {:vendor => {:role => :name}}
|
28
|
+
# match :name, :to => :by_vendor_name # maps to named scope
|
29
|
+
# you can also write your own join:
|
30
|
+
#
|
31
|
+
# match :name, :joins => "INNER JOIN products ON products.id = bookmarks.id"
|
32
|
+
def match(key, options = {})
|
33
|
+
@params << param!(key, options)
|
34
|
+
end
|
35
|
+
|
36
|
+
def render(params)
|
37
|
+
query.render(params)
|
38
|
+
end
|
39
|
+
|
40
|
+
def find(key)
|
41
|
+
query.find(key)
|
42
|
+
end
|
43
|
+
|
44
|
+
def query
|
45
|
+
@query ||= query_class.new(self)
|
46
|
+
end
|
47
|
+
|
48
|
+
def keys
|
49
|
+
params.map(&:key)
|
50
|
+
end
|
51
|
+
|
52
|
+
def find_type(key, options = {})
|
53
|
+
model.model_type(key, options)
|
54
|
+
end
|
55
|
+
|
56
|
+
def model
|
57
|
+
@model ||= "::Deli::Adapters::#{config.default_adapter.to_s.camelize}::Model".constantize.new(model_name)
|
58
|
+
end
|
59
|
+
|
60
|
+
def query_class
|
61
|
+
@query_class ||= "::Deli::Adapters::#{config.default_adapter.to_s.camelize}::Query".constantize
|
62
|
+
end
|
63
|
+
|
64
|
+
def find_adapter(options = {})
|
65
|
+
(options[:adapter] || config.default_adapter).to_s.camelize
|
66
|
+
end
|
67
|
+
|
68
|
+
def param!(key, options = {})
|
69
|
+
"::Deli::Adapters::#{find_adapter(options)}::#{find_type(key.to_s, options).to_s.camelize}".constantize.new(
|
70
|
+
key,
|
71
|
+
options.reverse_merge(:model_name => self.model_name, :parser => self)
|
72
|
+
)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
data/lib/deli/helper.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
module Deli
|
2
|
+
module Helper
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
class_attribute :query_controller
|
7
|
+
end
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
def queries(*args, &block)
|
11
|
+
options = args.extract_options!
|
12
|
+
name = args.shift || self.class.name.underscore.gsub("_controller", "").singularize
|
13
|
+
self.query_controller = ::Deli::Controller.new(name, options, &block)
|
14
|
+
|
15
|
+
self.send :before_filter, :deli, :only => :index
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
module InstanceMethods
|
20
|
+
def deli_controller
|
21
|
+
@deli_controller ||= self.is_a?(::ActionController::Base) ? self.class.query_controller : self.controller.class.query_controller
|
22
|
+
end
|
23
|
+
|
24
|
+
# The query hash you want to use to paginate.
|
25
|
+
def deli
|
26
|
+
@deli ||= deli_controller.render(query_params) if deli_controller.present?
|
27
|
+
@deli
|
28
|
+
end
|
29
|
+
|
30
|
+
# Simple method to give you the query parameters we're interested in.
|
31
|
+
def query_params
|
32
|
+
@query_params ||= ::Deli::Query.parse_query(request.query_string)
|
33
|
+
end
|
34
|
+
|
35
|
+
# with_params(admin_user_membership_path(@user, @membership), :sort => "name")
|
36
|
+
# merges url with existing params
|
37
|
+
def with_params(path, new_params = {})
|
38
|
+
params = query_params.merge(new_params.stringify_keys)
|
39
|
+
return path if params.blank?
|
40
|
+
query_string = ::Deli::Query.build_query(params)
|
41
|
+
"#{path}?#{query_string}"
|
42
|
+
end
|
43
|
+
|
44
|
+
def param_operators(key)
|
45
|
+
deli_controller.find(key).operators
|
46
|
+
end
|
47
|
+
|
48
|
+
def deli_keys
|
49
|
+
deli_controller.keys
|
50
|
+
end
|
51
|
+
|
52
|
+
def queryable_keys
|
53
|
+
deli_controller.keys - [:sort, :page, :limit]
|
54
|
+
end
|
55
|
+
|
56
|
+
def queryable_options
|
57
|
+
queryable_keys.map {|i| [i.titleize, i.to_s]}
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
data/lib/deli/model.rb
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
module Deli
|
2
|
+
module Pagination
|
3
|
+
def paginate(options)
|
4
|
+
options = options.dup
|
5
|
+
options[:page] = ((options[:offset] || 0) / options[:limit]).ceil if !options[:page] && options[:limit]
|
6
|
+
options[:per_page] ||= options[:limit]
|
7
|
+
|
8
|
+
pagenum = options.fetch(:page) { raise ArgumentError, ":page parameter required" }
|
9
|
+
per_page = options.delete(:per_page) || self.per_page
|
10
|
+
total = options.delete(:total_entries)
|
11
|
+
|
12
|
+
count_options = options.delete(:count)
|
13
|
+
options.delete(:page)
|
14
|
+
|
15
|
+
rel = limit(per_page.to_i).page(pagenum)
|
16
|
+
|
17
|
+
rel = rel.apply_finder_options(options) if options.any?
|
18
|
+
rel.total_entries = total.to_i unless total.blank?
|
19
|
+
rel
|
20
|
+
end
|
21
|
+
|
22
|
+
def page(num)
|
23
|
+
rel = scoped.extending(::Deli::Pagination::Collection)
|
24
|
+
pagenum = [num.nil? ? 1 : num, 1].max
|
25
|
+
per_page = rel.limit_value || ::Deli.configuration.per_page
|
26
|
+
rel = rel.offset((pagenum.to_i - 1) * per_page.to_i)
|
27
|
+
rel = rel.limit(per_page) unless rel.limit_value
|
28
|
+
rel
|
29
|
+
end
|
30
|
+
|
31
|
+
module Collection
|
32
|
+
def total_count
|
33
|
+
@total_count ||= proxy_scope.count(proxy_options.except(:limit, :offset, :order))
|
34
|
+
end
|
35
|
+
|
36
|
+
def has_next?
|
37
|
+
last_page > current_page
|
38
|
+
end
|
39
|
+
|
40
|
+
def has_prev?
|
41
|
+
current_page > first_page
|
42
|
+
end
|
43
|
+
|
44
|
+
def start_count
|
45
|
+
@start_count ||= (((current_page || 1) - 1) * page_size)
|
46
|
+
end
|
47
|
+
|
48
|
+
def end_count
|
49
|
+
@end_count ||= start_count + size
|
50
|
+
end
|
51
|
+
|
52
|
+
def current_page
|
53
|
+
unless @current_page
|
54
|
+
if offset_value.blank? || offset_value.zero?
|
55
|
+
@current_page = 1
|
56
|
+
else
|
57
|
+
@current_page = (offset_value.to_f / limit_value).to_i + 1
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
@current_page
|
62
|
+
end
|
63
|
+
|
64
|
+
def next_page
|
65
|
+
unless @next_page
|
66
|
+
@next_page = current_page + 1 > last_page ? last_page : current_page + 1
|
67
|
+
end
|
68
|
+
|
69
|
+
@next_page
|
70
|
+
end
|
71
|
+
|
72
|
+
def prev_page
|
73
|
+
unless @prev_page
|
74
|
+
@prev_page = current_page - 1 < first_page ? first_page : current_page - 1
|
75
|
+
end
|
76
|
+
|
77
|
+
@prev_page
|
78
|
+
end
|
79
|
+
|
80
|
+
def first_page
|
81
|
+
1
|
82
|
+
end
|
83
|
+
|
84
|
+
def last_page
|
85
|
+
page_count
|
86
|
+
end
|
87
|
+
|
88
|
+
def page_size
|
89
|
+
@page_size ||= limit_value
|
90
|
+
end
|
91
|
+
|
92
|
+
def page_count
|
93
|
+
@page_count ||= (total_count.to_f / page_size).ceil
|
94
|
+
end
|
95
|
+
|
96
|
+
# a workaround for AR 3.0.x that returns 0 for #count when page > 1
|
97
|
+
# if +limit_value+ is specified, load all the records and count them
|
98
|
+
if defined?(::ActiveRecord) && ::ActiveRecord::VERSION::STRING < '3.1'
|
99
|
+
def count #:nodoc:
|
100
|
+
limit_value ? length : super
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def total_count #:nodoc:
|
105
|
+
# #count overrides the #select which could include generated columns referenced in #order, so skip #order here, where it's irrelevant to the result anyway
|
106
|
+
c = except(:offset, :limit, :order)
|
107
|
+
# a workaround for 3.1.beta1 bug. see: https://github.com/rails/rails/issues/406
|
108
|
+
c = c.reorder nil
|
109
|
+
# Remove includes only if they are irrelevant
|
110
|
+
c = c.except(:includes) unless references_eager_loaded_tables?
|
111
|
+
# .group returns an OrderdHash that responds to #count
|
112
|
+
c = c.count
|
113
|
+
c.respond_to?(:count) ? c.count : c
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
data/lib/deli/param.rb
ADDED
@@ -0,0 +1,189 @@
|
|
1
|
+
module Deli
|
2
|
+
class Param
|
3
|
+
module Time
|
4
|
+
def parse(value, as = :time)
|
5
|
+
values = []
|
6
|
+
|
7
|
+
value.to_s.split(/[\s,\+]/).each do |string|
|
8
|
+
if string =~ /([^\.]+)?(\.\.)([^\.]+)?/
|
9
|
+
starts_on, operator, ends_on = $1, $2, $3
|
10
|
+
range = []
|
11
|
+
range << parse_value(starts_on, [">="]) if !!(starts_on.present? && starts_on =~ /^\d/)
|
12
|
+
range << parse_value(ends_on, ["<="]) if !!(ends_on.present? && ends_on =~ /^\d/)
|
13
|
+
values << range
|
14
|
+
else
|
15
|
+
values << [parse_value(string, ["="])]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
values
|
20
|
+
end
|
21
|
+
|
22
|
+
def parse_value(value, operators)
|
23
|
+
super(::Time.zone.parse(value), operators)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
module Date
|
28
|
+
include Time
|
29
|
+
|
30
|
+
def parse(value)
|
31
|
+
super(value, :date)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
module String
|
36
|
+
def parse(value)
|
37
|
+
arrays = value.split(/(?:[\s|\+]OR[\s|\+]|\||,)/).map do |node|
|
38
|
+
values = []
|
39
|
+
|
40
|
+
# ([\+\-\^]?[\w@\-_\s\d\.\$]+|-?\'[\w@-_\s\d\+\.\$]+\')
|
41
|
+
node.scan(/([\+\-\^]?[\w@_\s\d\.\$]+|-?\'[\w@-_\s\d\+\.\$]+\')/).flatten.each do |token|
|
42
|
+
token.gsub!(/^\+?-+/, "")
|
43
|
+
negation = $& && $&.length > 0
|
44
|
+
token.gsub!(/^\'(.+)\'$/, "\\1")
|
45
|
+
exact = $& && $&.length > 0
|
46
|
+
|
47
|
+
if negation
|
48
|
+
operators = [exact ? "!=" : "!~"]
|
49
|
+
else
|
50
|
+
operators = [exact ? "=" : "=~"]
|
51
|
+
end
|
52
|
+
|
53
|
+
operators << "^" if token =~ /^\+?\-?\^/
|
54
|
+
operators << "$" if token =~ /\$$/
|
55
|
+
|
56
|
+
values << parse_value(clean(token), operators)
|
57
|
+
end
|
58
|
+
|
59
|
+
values
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
module Number
|
65
|
+
def parse(value)
|
66
|
+
values = []
|
67
|
+
|
68
|
+
value.to_s.split(/[,\|]/).each do |string|
|
69
|
+
if string =~ /([^\.]+)?(\.{2})([^\.]+)?/
|
70
|
+
starts_on, operator, ends_on = $1, $2, $3
|
71
|
+
range = []
|
72
|
+
range << parse_value(starts_on, [">="]) if starts_on.present? && starts_on =~ /^\d/
|
73
|
+
range << parse_value(ends_on, ["<="]) if ends_on.present? && ends_on =~ /^\d/
|
74
|
+
values << range
|
75
|
+
else
|
76
|
+
values << [parse_value(string, ["="])]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
values
|
81
|
+
end
|
82
|
+
|
83
|
+
def parse_value(value, operators)
|
84
|
+
super(value.to_i, operators) # or to_f ?
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
module Limit
|
89
|
+
def parse(value)
|
90
|
+
result = value.to_s.scan(/(\d+)/).flatten[0]
|
91
|
+
result.present? ? result.to_i : self.default
|
92
|
+
end
|
93
|
+
|
94
|
+
def render(value)
|
95
|
+
parse(value)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
module Order
|
100
|
+
def parse(value)
|
101
|
+
value.split(",").map do |string|
|
102
|
+
string.scan(/([\w-]+[^\-\+])([\+\-])?/).map do |token, operator|
|
103
|
+
operator = operator == "-" ? "-" : "+"
|
104
|
+
token = clean(token)
|
105
|
+
|
106
|
+
if controller.present?
|
107
|
+
param = controller.find(token)
|
108
|
+
token = param.table_key
|
109
|
+
end
|
110
|
+
|
111
|
+
{:namespace => namespace, :key => token, :operators => [operator]}
|
112
|
+
end
|
113
|
+
end.flatten
|
114
|
+
end
|
115
|
+
|
116
|
+
def order_hash(value)
|
117
|
+
value.split(",").inject(ActiveSupport::OrderedHash.new) do |hash, string|
|
118
|
+
string.scan(/([\w-]+[^\-\+])([\+\-])?/).each do |token, operator|
|
119
|
+
hash[clean(token)] = operator == "-" ? "-" : "+"
|
120
|
+
end
|
121
|
+
hash
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
module Offset
|
127
|
+
def parse(value)
|
128
|
+
result = value.to_s.scan(/(\d+)/).flatten[0]
|
129
|
+
result.present? ? result.to_i : self.default
|
130
|
+
end
|
131
|
+
|
132
|
+
def render(value)
|
133
|
+
parse(value)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
# Todo
|
138
|
+
module Geo
|
139
|
+
def parse(value)
|
140
|
+
value.to_s.split(/,\s*/).map(&:to_f) # [41.31419, -88.1847]
|
141
|
+
end
|
142
|
+
|
143
|
+
def render(value)
|
144
|
+
parse(value)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
attr_accessor :controller, :key, :model_name, :namespace, :exact, :default
|
149
|
+
|
150
|
+
def initialize(key, options = {})
|
151
|
+
self.controller = options[:controller]
|
152
|
+
self.key = key.to_s
|
153
|
+
self.model_name = options[:model_name]
|
154
|
+
self.namespace = self.model_name.to_s.pluralize.to_sym if model_name.present?
|
155
|
+
self.exact = options[:exact] || false
|
156
|
+
self.default = options[:default]
|
157
|
+
end
|
158
|
+
|
159
|
+
def parse(value)
|
160
|
+
value
|
161
|
+
end
|
162
|
+
|
163
|
+
def render(value)
|
164
|
+
value
|
165
|
+
end
|
166
|
+
|
167
|
+
def parse_value(value, operators)
|
168
|
+
{
|
169
|
+
:namespace => namespace,
|
170
|
+
:key => key,
|
171
|
+
:operators => operators,
|
172
|
+
:value => value
|
173
|
+
}
|
174
|
+
end
|
175
|
+
|
176
|
+
def inspect
|
177
|
+
"#<#{self.class.name} @key=#{key.inspect} @model_name=#{model_name.inspect}>"
|
178
|
+
end
|
179
|
+
|
180
|
+
protected
|
181
|
+
def clean(string)
|
182
|
+
string.gsub(/^-/, "").gsub(/^\+-/, "").gsub(/^'|'$/, "").gsub("+", " ").gsub(/^\^/, "").gsub(/\$$/, "").strip
|
183
|
+
end
|
184
|
+
|
185
|
+
def model_class
|
186
|
+
@model_class ||= model_name.to_s.camelize.constantize
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|