muster 0.0.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.
- data/.gitignore +18 -0
- data/.rspec +2 -0
- data/.yardopts +1 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +132 -0
- data/Rakefile +9 -0
- data/lib/muster.rb +3 -0
- data/lib/muster/rack.rb +72 -0
- data/lib/muster/strategies.rb +6 -0
- data/lib/muster/strategies/active_record.rb +118 -0
- data/lib/muster/strategies/filter_expression.rb +142 -0
- data/lib/muster/strategies/hash.rb +93 -0
- data/lib/muster/strategies/pagination.rb +111 -0
- data/lib/muster/strategies/rack.rb +89 -0
- data/lib/muster/strategies/sort_expression.rb +75 -0
- data/lib/muster/version.rb +4 -0
- data/muster.gemspec +24 -0
- data/spec/muster/rack_spec.rb +37 -0
- data/spec/muster/strategies/active_record_spec.rb +137 -0
- data/spec/muster/strategies/filter_expression_spec.rb +126 -0
- data/spec/muster/strategies/hash_spec.rb +90 -0
- data/spec/muster/strategies/pagination_spec.rb +74 -0
- data/spec/muster/strategies/sort_expression_spec.rb +94 -0
- data/spec/spec_helper.rb +8 -0
- metadata +134 -0
data/.gitignore
ADDED
data/.rspec
ADDED
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--protected
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Christopher H. Laco
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
# Muster
|
2
|
+
|
3
|
+
Muster is a gem that turns query string options of varying formats into data structures suitable for
|
4
|
+
easier consumption in things like AR and DataMapper scopes and queries, making API development just a little bit easier.
|
5
|
+
|
6
|
+
require 'muster'
|
7
|
+
|
8
|
+
use Muster::Rack, Muster::Strategies::ActiveRecord, :fields => [:select, :order]
|
9
|
+
|
10
|
+
# GET /people?select=id,name&order=name:desc
|
11
|
+
# in your routes/controllers
|
12
|
+
query = env['muster.query']
|
13
|
+
|
14
|
+
@people = Person.select( query[:select] ).order( query[:order] )
|
15
|
+
|
16
|
+
## Strategies
|
17
|
+
|
18
|
+
The following types of strategies are supported. You can combine them in Rack any way you see fit to match the query string options
|
19
|
+
you want to support.
|
20
|
+
|
21
|
+
### Rack
|
22
|
+
|
23
|
+
Returns the query as parsed by Rack::Utils#parse_query.
|
24
|
+
|
25
|
+
?name=value1&name=value2&choice=1&choice=1
|
26
|
+
|
27
|
+
{ 'name' => ['value1', 'value2'], 'choice' => ['1', '1'] }
|
28
|
+
|
29
|
+
### Hash
|
30
|
+
|
31
|
+
Same as Rack but with support for delimited value separation and unique value detection.
|
32
|
+
|
33
|
+
?name=value1,value2&choice=1&choice=1
|
34
|
+
|
35
|
+
{ 'name' => ['value1', 'value2'], 'choice' => '1' }
|
36
|
+
|
37
|
+
### FilterExpression
|
38
|
+
|
39
|
+
Allows name value pairs to be specified in the query string values for use in filtering methods that take Hashes.
|
40
|
+
Include delimited value and unique value support from above.
|
41
|
+
|
42
|
+
?filter=id:1&filter=name:food #=> { 'filter' => {'id' => '1', 'name' => 'food'} }
|
43
|
+
?filter=id:1&filter=id:2 #=> { 'filter' => {'id' => ['1', '2']} }
|
44
|
+
?filter=id:1|2 #=> { 'filter' => {'id' => ['1', '2']} }
|
45
|
+
?filter=id:1,name:food #=> { 'filter' => {'id' => '1', 'name' => 'food'} }
|
46
|
+
|
47
|
+
### SortExpression
|
48
|
+
|
49
|
+
Returns options with support for dirctional indicators for use in sorting.
|
50
|
+
|
51
|
+
?order=name&order=age #=> { 'order' => ['name asc', 'age asc'] }
|
52
|
+
?order=name:asc&age:desc #=> { 'order' => ['name asc', 'age desc'] }
|
53
|
+
|
54
|
+
### Pagination
|
55
|
+
|
56
|
+
Returns options to support pagination with logic for default page size, not-a-number checks and offset calculations.
|
57
|
+
|
58
|
+
?page=2&per_page=5 #=> { 'pagination' => {'page' => 2, 'per_page' => 5}, 'limit' => 5, 'offset' => 5 }
|
59
|
+
?page=a&page_size=-2 #=> { 'pagination' => {'page' => 1, 'per_page' => 30}, 'limit' => 30, 'offset' => nil}
|
60
|
+
|
61
|
+
|
62
|
+
### ActiveRecord
|
63
|
+
|
64
|
+
Combines many of the strategies above to output ActiveRecord Query interface compatible options.
|
65
|
+
|
66
|
+
?select=id,name&where=status:new&order=name:desc&page=3&page_size=10
|
67
|
+
|
68
|
+
{ 'select' => ['id', 'name'], 'where' => {'status' => 'new'}, 'order' => 'name desc', 'limit' => 10, 'offset' => 20, 'pagination' => {:page => 3, :per_page => 10} }
|
69
|
+
|
70
|
+
query = env['muster.query']
|
71
|
+
Person.select( query[:select] ).where( query[:where] ).order( query[:order] ).offset( query[:offset] ).limit( query[:limit] )
|
72
|
+
|
73
|
+
If you are using WillPaginate, you can also pass in :pagination:
|
74
|
+
|
75
|
+
Person.paginate( query[:paginate] )
|
76
|
+
|
77
|
+
## Installation
|
78
|
+
|
79
|
+
Add this line to your application's Gemfile:
|
80
|
+
|
81
|
+
gem 'muster'
|
82
|
+
|
83
|
+
And then execute:
|
84
|
+
|
85
|
+
$ bundle
|
86
|
+
|
87
|
+
Or install it yourself as:
|
88
|
+
|
89
|
+
$ gem install muster
|
90
|
+
|
91
|
+
## Usage
|
92
|
+
|
93
|
+
### In any Rack application:
|
94
|
+
|
95
|
+
require 'muster'
|
96
|
+
|
97
|
+
use Muster::Rack, Muster::Strategies::ActiveRecord, :fields => [:select, :order]
|
98
|
+
|
99
|
+
# GET /people?select=id,name&order=name:desc
|
100
|
+
# in your routes/controllers
|
101
|
+
query = env['muster.query']
|
102
|
+
|
103
|
+
@people = Person.select( query[:select] ).order( query[:order] )
|
104
|
+
|
105
|
+
You can combine multiple strategies, and their results will be merged
|
106
|
+
|
107
|
+
use Muster::Rack, Muster::Strategies::Hash, :field => :select
|
108
|
+
use Muster::Rack, Muster::Strategies::ActiveRecord, :field => :order
|
109
|
+
|
110
|
+
# GET /people?select=id,name&order=name:desc
|
111
|
+
# in your routes/controllers
|
112
|
+
query = env['muster.query']
|
113
|
+
|
114
|
+
@people = Person.select( query[:select] ).order( query[:order] )
|
115
|
+
|
116
|
+
|
117
|
+
### In any code:
|
118
|
+
|
119
|
+
require 'muster'
|
120
|
+
|
121
|
+
strategy = Muster::Strategies::Hash.new
|
122
|
+
query = strategy.parse(request.query_string)
|
123
|
+
people = Person.select( query[:select] ).order( query[:order] )
|
124
|
+
|
125
|
+
## Contributing
|
126
|
+
|
127
|
+
1. Fork it from https://github.com/claco/muster
|
128
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
129
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
130
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
131
|
+
5. Create new Pull Request
|
132
|
+
|
data/Rakefile
ADDED
data/lib/muster.rb
ADDED
data/lib/muster/rack.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'rack'
|
2
|
+
|
3
|
+
module Muster
|
4
|
+
|
5
|
+
# Rack middleware plugin for Muster query string parsing
|
6
|
+
#
|
7
|
+
# @example
|
8
|
+
#
|
9
|
+
# app = Rack::Builder.new do
|
10
|
+
# use Rack::Muster, Muster::Strategies::Hash, :fields => [:name, :choices]
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# # GET /?name=bob&choices=1&choices=2
|
14
|
+
# match '/' do
|
15
|
+
# env['muster.query'] #=> {'name' => 'bob', 'choices' => ['1', '2']}
|
16
|
+
# end
|
17
|
+
class Rack
|
18
|
+
|
19
|
+
# @attribute [r] app
|
20
|
+
# @return [Object] Rack application middleware is running under
|
21
|
+
attr_reader :app
|
22
|
+
|
23
|
+
# @attribute [r] strategy
|
24
|
+
# @return [Muster::Strategies::Rack] Muster Strategy to run
|
25
|
+
attr_reader :strategy
|
26
|
+
|
27
|
+
# @attribute [r] options
|
28
|
+
# @return [Hash] options to pass to strategy
|
29
|
+
attr_reader :options
|
30
|
+
|
31
|
+
# Key in ENV where processed query string are stored
|
32
|
+
QUERY = 'muster.query'.freeze
|
33
|
+
|
34
|
+
# Key in ENV where the query string that was processed is stored
|
35
|
+
QUERY_STRING = 'muster.query_string'.freeze
|
36
|
+
|
37
|
+
# Creates a new Rack::Muster middleware instance
|
38
|
+
#
|
39
|
+
# @param app [String] Rack application
|
40
|
+
# @param strategy [Muster::Strategies::Rack] Muster query string parsing strategy to run
|
41
|
+
# @param options [Hash] options to pass to the specified strategy
|
42
|
+
#
|
43
|
+
# @example
|
44
|
+
#
|
45
|
+
# middleware = Muster::Rack.new(app, Muster::Strategies::Hash, :fields => [:name, :choices])
|
46
|
+
#
|
47
|
+
# strategy = Muster::Strategies::Hash.new(:fields => [:name, :choices])
|
48
|
+
# middleware = Muster::Rack.new(app, strategy)
|
49
|
+
def initialize( app, strategy, options={} )
|
50
|
+
@app = app
|
51
|
+
@strategy = strategy
|
52
|
+
@options = options
|
53
|
+
end
|
54
|
+
|
55
|
+
# Handle Rack request
|
56
|
+
#
|
57
|
+
# @param env [Hash] Rack environment
|
58
|
+
#
|
59
|
+
# @return [Array]
|
60
|
+
def call( env )
|
61
|
+
request = ::Rack::Request.new(env)
|
62
|
+
parser = self.strategy.kind_of?(Class) ? self.strategy.new(options) : self.strategy
|
63
|
+
|
64
|
+
env[QUERY] ||= {}
|
65
|
+
env[QUERY].merge! parser.parse(request.query_string)
|
66
|
+
env[QUERY_STRING] = request.query_string
|
67
|
+
|
68
|
+
@app.call(env)
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
require 'active_support/core_ext/array/wrap'
|
2
|
+
require 'active_support/hash_with_indifferent_access'
|
3
|
+
require 'muster/strategies/hash'
|
4
|
+
require 'muster/strategies/filter_expression'
|
5
|
+
require 'muster/strategies/pagination'
|
6
|
+
require 'muster/strategies/sort_expression'
|
7
|
+
|
8
|
+
module Muster
|
9
|
+
module Strategies
|
10
|
+
|
11
|
+
# Query string parsing strategy that outputs ActiveRecord Query compatible options
|
12
|
+
#
|
13
|
+
# @example
|
14
|
+
#
|
15
|
+
# strategy = Muster::Strategies::ActiveRecord.new
|
16
|
+
# results = strategy.parse('select=id,name&where=status:new&order=name:desc')
|
17
|
+
#
|
18
|
+
# # { 'select' => ['id', 'name'], :where => {'status' => 'new}, :order => 'name desc' }
|
19
|
+
# #
|
20
|
+
# # Person.select( results[:select] ).where( results[:where] ).order( results[:order] )
|
21
|
+
class ActiveRecord < Muster::Strategies::Rack
|
22
|
+
|
23
|
+
# Processes a query string and returns a hash of its fields/values
|
24
|
+
#
|
25
|
+
# @param query_string [String] the query string to parse
|
26
|
+
#
|
27
|
+
# @return [Hash]
|
28
|
+
#
|
29
|
+
# @example
|
30
|
+
#
|
31
|
+
# results = strategy.parse('select=id,name&where=status:new&order=name:desc')
|
32
|
+
#
|
33
|
+
# # { 'select' => ['id', 'name'], :where => {'status' => 'new}, :order => 'name desc' }
|
34
|
+
def parse( query_string )
|
35
|
+
pagination = self.parse_pagination( query_string )
|
36
|
+
|
37
|
+
parameters = ActiveSupport::HashWithIndifferentAccess.new(
|
38
|
+
:select => self.parse_select(query_string),
|
39
|
+
:order => self.parse_order(query_string),
|
40
|
+
:limit => pagination[:limit],
|
41
|
+
:offset => pagination[:offset],
|
42
|
+
:where => self.parse_where(query_string)
|
43
|
+
)
|
44
|
+
|
45
|
+
parameters.regular_writer('pagination', pagination[:pagination].symbolize_keys)
|
46
|
+
|
47
|
+
return parameters
|
48
|
+
end
|
49
|
+
|
50
|
+
protected
|
51
|
+
|
52
|
+
# Returns select clauses for AR queries
|
53
|
+
#
|
54
|
+
# @param query_string [String] the original query string to parse select clauses from
|
55
|
+
#
|
56
|
+
# @return [Array]
|
57
|
+
#
|
58
|
+
# @example
|
59
|
+
#
|
60
|
+
# value = self.parse_select('select=id,name') #=> ['id', 'name']
|
61
|
+
def parse_select( query_string )
|
62
|
+
strategy = Muster::Strategies::Hash.new(:field => :select)
|
63
|
+
results = strategy.parse(query_string)
|
64
|
+
|
65
|
+
return Array.wrap( results[:select] )
|
66
|
+
end
|
67
|
+
|
68
|
+
# Returns order by clauses for AR queries
|
69
|
+
#
|
70
|
+
# @param query_string [String] the original query string to parse order clauses from
|
71
|
+
#
|
72
|
+
# @return [Array]
|
73
|
+
#
|
74
|
+
# @example
|
75
|
+
#
|
76
|
+
# value = self.parse_order('order=name:desc') #=> ['name asc']
|
77
|
+
def parse_order( query_string )
|
78
|
+
strategy = Muster::Strategies::SortExpression.new(:field => :order)
|
79
|
+
results = strategy.parse(query_string)
|
80
|
+
|
81
|
+
return Array.wrap( results[:order] )
|
82
|
+
end
|
83
|
+
|
84
|
+
# Returns pagination information for AR queries
|
85
|
+
#
|
86
|
+
# @param query_string [String] the original query string to parse pagination from
|
87
|
+
#
|
88
|
+
# @return [Hash]
|
89
|
+
#
|
90
|
+
# @example
|
91
|
+
#
|
92
|
+
# value = self.parse_pagination('page=2&page_size=10') #=> { 'pagination' => {:page => 2, :per_page => 10}, 'limit' => 10, 'offset' => 10 }
|
93
|
+
def parse_pagination( query_string )
|
94
|
+
strategy = Muster::Strategies::Pagination.new(:fields => [:pagination, :limit, :offset])
|
95
|
+
results = strategy.parse(query_string)
|
96
|
+
|
97
|
+
return results
|
98
|
+
end
|
99
|
+
|
100
|
+
# Returns where clauses for AR queries
|
101
|
+
#
|
102
|
+
# @param query_string [String] the original query string to parse where statements from
|
103
|
+
#
|
104
|
+
# @return [Hash]
|
105
|
+
#
|
106
|
+
# @example
|
107
|
+
#
|
108
|
+
# value = self.parse_where('where=id:1') #=> {'id' => '1'}
|
109
|
+
def parse_where( query_string )
|
110
|
+
strategy = Muster::Strategies::FilterExpression.new(:field => :where)
|
111
|
+
results = strategy.parse(query_string)
|
112
|
+
|
113
|
+
return results[:where] || {}
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
require 'active_support/core_ext/array/wrap'
|
2
|
+
require 'muster/strategies/hash'
|
3
|
+
|
4
|
+
module Muster
|
5
|
+
module Strategies
|
6
|
+
|
7
|
+
# Query string parsing strategy with additional value handling options for separating filtering expressions
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
#
|
11
|
+
# strategy = Muster::Strategies::FilterExpression.new
|
12
|
+
# results = strategy.parse('where=id:1&name:Bob') #=> { 'where' => {'id' => '1', 'name' => 'Bob'} }
|
13
|
+
class FilterExpression < Muster::Strategies::Hash
|
14
|
+
|
15
|
+
# @attribute [r] expression_separator
|
16
|
+
# @return [String,RegEx] when specified, each field value will be split into multiple expressions using the specified separator
|
17
|
+
attr_reader :expression_separator
|
18
|
+
|
19
|
+
# @attribute [r] field_separator
|
20
|
+
# @return [String,RegEx] when specified, each expression will be split into multiple field/values using the specified separator
|
21
|
+
attr_reader :field_separator
|
22
|
+
|
23
|
+
# Create a new Hash parsing strategy
|
24
|
+
#
|
25
|
+
# @param [Hash] options the options available for this method
|
26
|
+
# @option options [optional,Array<Symbol>] :fields when specified, only parse the specified fields
|
27
|
+
# You may also use :field if you only intend to pass one field
|
28
|
+
# @option options [optional,String,RegEx] :expression_separator (/,\s*/) when specified, splits the query string value into multiple expressions
|
29
|
+
# You may pass the separator as a string or a regular expression
|
30
|
+
# @option options [optional,String,RegEx] :field_separator (:) when specified, splits the expression value into multiple field/values
|
31
|
+
# You may pass the separator as a string or a regular expression
|
32
|
+
# @option options [optional,String,RegEx] :value_separator (|) when specified, splits the field value into multiple values
|
33
|
+
# You may pass the separator as a string or a regular expression
|
34
|
+
# @option options [optional,Boolean] :unique_values (true) when true, ensures field values do not contain duplicates
|
35
|
+
#
|
36
|
+
# @example
|
37
|
+
#
|
38
|
+
# strategy = Muster::Strategies::FilterExpression.new
|
39
|
+
# strategy = Muster::Strategies::FilterExpression.new(:unique_values => false)
|
40
|
+
def initialize( options={} )
|
41
|
+
super
|
42
|
+
|
43
|
+
@expression_separator = self.options.fetch(:expression_separator, /,\s*/)
|
44
|
+
@field_separator = self.options.fetch(:field_separator, ':')
|
45
|
+
@value_separator = self.options.fetch(:value_separator, '|')
|
46
|
+
end
|
47
|
+
|
48
|
+
# Processes a query string and returns a hash of its fields/values
|
49
|
+
#
|
50
|
+
# @param query_string [String] the query string to parse
|
51
|
+
#
|
52
|
+
# @return [Hash]
|
53
|
+
#
|
54
|
+
# @example
|
55
|
+
#
|
56
|
+
# results = strategy.parse('where=id:1&name:Bob') #=> { 'where' => {'id' => '1', 'name' => 'Bob'} }
|
57
|
+
def parse( query_string )
|
58
|
+
parameters = self.fields_to_parse(query_string)
|
59
|
+
|
60
|
+
parameters.each do |key, value|
|
61
|
+
parameters[key] = self.separate_expressions(value)
|
62
|
+
parameters[key] = self.separate_fields(parameters[key])
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
protected
|
67
|
+
|
68
|
+
# Separates values into an Array of expressions using :expression_separator
|
69
|
+
#
|
70
|
+
# @param value [String,Array] the original query string field value to separate
|
71
|
+
#
|
72
|
+
# @return [String,Array] String if a single value exists, Array otherwise
|
73
|
+
#
|
74
|
+
# @example
|
75
|
+
#
|
76
|
+
# value = self.separate_values('where=id:1') #=> {'where' => 'id:1'}
|
77
|
+
# value = self.separate_values('where=id:1,id:2') #=> {'where' => ['id:1', 'id:2']}
|
78
|
+
def separate_expressions( value )
|
79
|
+
values = Array.wrap(value)
|
80
|
+
|
81
|
+
values = values.map do |value|
|
82
|
+
value.split(self.expression_separator)
|
83
|
+
end.flatten
|
84
|
+
|
85
|
+
return (values.size > 1) ? values : values.first
|
86
|
+
end
|
87
|
+
|
88
|
+
# Separates expression field values into an Hash of expression filters using :field_separator
|
89
|
+
#
|
90
|
+
# @param value [String,Array] the expressions field value to separate
|
91
|
+
#
|
92
|
+
# @return [Hash]
|
93
|
+
#
|
94
|
+
# @example
|
95
|
+
#
|
96
|
+
# value = self.separate_fields('id:1') #=> {'id' => '1'}
|
97
|
+
# value = self.separate_values('id:1|2') #=> {'id' => '1|2'}
|
98
|
+
def separate_fields( value )
|
99
|
+
values = Array.wrap(value)
|
100
|
+
|
101
|
+
filters = {}
|
102
|
+
|
103
|
+
values.each do |value|
|
104
|
+
name, value = value.split(self.field_separator, 2)
|
105
|
+
|
106
|
+
if self.value_separator.present?
|
107
|
+
value = self.separate_values(value)
|
108
|
+
end
|
109
|
+
|
110
|
+
filters[name] = filters.has_key?(name) ? [filters[name], value].flatten : value
|
111
|
+
|
112
|
+
if self.unique_values == true && filters[name].instance_of?(Array)
|
113
|
+
filters[name].uniq!
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
return filters
|
118
|
+
end
|
119
|
+
|
120
|
+
# Separates expression filter values into an Array of expression filter values using :value_separator
|
121
|
+
#
|
122
|
+
# @param value [String,Array] the expressions filter value to separate
|
123
|
+
#
|
124
|
+
# @return [String,Array] String if a single value exists, Array otherwise
|
125
|
+
#
|
126
|
+
# @example
|
127
|
+
#
|
128
|
+
# value = self.separate_values('1') #=> '1'
|
129
|
+
# value = self.separate_values('1|2') #=> ['1', '2']
|
130
|
+
def separate_values( value )
|
131
|
+
values = Array.wrap(value)
|
132
|
+
|
133
|
+
values = values.map do |value|
|
134
|
+
value.split(self.value_separator)
|
135
|
+
end.flatten
|
136
|
+
|
137
|
+
return (values.size > 1) ? values : value
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|