deli 0.5.0
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.
- 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
|