Skip to content

Commit

Permalink
Merge remote branch 'core/custom-display-method' into development
Browse files Browse the repository at this point in the history
  • Loading branch information
cykod committed Oct 6, 2010
2 parents 7557779 + 74ad82b commit 51dd05f
Show file tree
Hide file tree
Showing 10 changed files with 209 additions and 15 deletions.
8 changes: 6 additions & 2 deletions app/models/end_user_segment_type.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,14 @@ def self.is(cls, group_field, field, source)
end

class UserLevelType < UserSegment::FieldType
register_operation :is, [['User Level', :option, {:options => EndUser.user_level_select_options}]]
def self.select_options
EndUser.user_level_select_options
end

register_operation :is, [['User Level', :array, {:class => UserLevelType}]]

def self.is(cls, group_field, field, user_level)
cls.scoped(:conditions => ["#{field} = ?", user_level])
cls.scoped(:conditions => ["#{field} in(?)", user_level])
end
end
end
2 changes: 2 additions & 0 deletions app/models/user_segment/field.rb
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,8 @@ def to_expr(opts={})
"\"#{arg}\""
elsif arg.is_a?(Time)
"\"#{arg.strftime('%m/%d/%Y %H:%M:%S')}\""
elsif arg.is_a?(Array)
'[' + arg.collect{ |v| v.is_a?(String) ? "\"#{v}\"" : v.to_s }.join(',') + ']'
else
arg.to_s
end
Expand Down
16 changes: 15 additions & 1 deletion app/models/user_segment/field_type.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def self.register_operation(operation, args=[], options={})
end

# converts a string to the correct type
# supported types are :integer, :float, :double, :date, :datetime, :option, :boolean, :model
# supported types are :integer, :float, :double, :date, :datetime, :option, :boolean, :model, :array
def self.convert_to(value, type, opts={})
return value if value.nil?

Expand Down Expand Up @@ -110,6 +110,18 @@ def self.convert_to(value, type, opts={})
else
return value if options.include?(value)
end
when :array
if value.is_a?(Array)
options = self.model_options(opts)
value.delete_if { |v| v == '' }
value = value.collect { |v| v.to_i } if options.size > 0 && options[0].is_a?(Array) && options[0][1].is_a?(Integer)
if options[0].is_a?(Array)
value.each { |v| return nil unless options.rassoc(v) }
else
value.each { |v| return nil unless options.include?(v) }
end
return value
end
end

nil
Expand Down Expand Up @@ -156,6 +168,8 @@ def self.field_output(mdl, handler_data, field)
value = value.inject(0) { |a,b| a + b } / value.size
when 'count'
value = value.size
else
value = info[:handler].send(info[:display_method], value) if info[:display_method] && info[:handler].respond_to?(info[:display_method])
end
else # index_by
value = data.send(display_field)
Expand Down
160 changes: 156 additions & 4 deletions app/models/user_segment_option_parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -672,16 +672,21 @@ def _nt_argument
if r6
r2 = r6
else
@index = i2
r2 = nil
r7 = _nt_array
if r7
r2 = r7
else
@index = i2
r2 = nil
end
end
end
end
end
s0 << r2
if r2
r7 = _nt_space
s0 << r7
r8 = _nt_space
s0 << r8
end
end
if s0.last
Expand All @@ -698,6 +703,153 @@ def _nt_argument
r0
end

module Array0
def val
elements[1]
end
end

module Array1
def arg
elements[1]
end

def more
elements[2]
end

end

module Array2
def eval(env={})
[arg.eval(env)] + more.elements.collect{ |e| e.val.eval(env) }
end
end

def _nt_array
start_index = index
if node_cache[:array].has_key?(index)
cached = node_cache[:array][index]
if cached
cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
@index = cached.interval.end
end
return cached
end

i0, s0 = index, []
if has_terminal?('[', false, index)
r1 = instantiate_node(SyntaxNode,input, index...(index + 1))
@index += 1
else
terminal_parse_failure('[')
r1 = nil
end
s0 << r1
if r1
i2 = index
r3 = _nt_string
if r3
r2 = r3
else
r4 = _nt_float
if r4
r2 = r4
else
r5 = _nt_integer
if r5
r2 = r5
else
r6 = _nt_boolean
if r6
r2 = r6
else
@index = i2
r2 = nil
end
end
end
end
s0 << r2
if r2
s7, i7 = [], index
loop do
i8, s8 = index, []
if has_terminal?(',', false, index)
r9 = instantiate_node(SyntaxNode,input, index...(index + 1))
@index += 1
else
terminal_parse_failure(',')
r9 = nil
end
s8 << r9
if r9
i10 = index
r11 = _nt_string
if r11
r10 = r11
else
r12 = _nt_float
if r12
r10 = r12
else
r13 = _nt_integer
if r13
r10 = r13
else
r14 = _nt_boolean
if r14
r10 = r14
else
@index = i10
r10 = nil
end
end
end
end
s8 << r10
end
if s8.last
r8 = instantiate_node(SyntaxNode,input, i8...index, s8)
r8.extend(Array0)
else
@index = i8
r8 = nil
end
if r8
s7 << r8
else
break
end
end
r7 = instantiate_node(SyntaxNode,input, i7...index, s7)
s0 << r7
if r7
if has_terminal?(']', false, index)
r15 = instantiate_node(SyntaxNode,input, index...(index + 1))
@index += 1
else
terminal_parse_failure(']')
r15 = nil
end
s0 << r15
end
end
end
if s0.last
r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
r0.extend(Array1)
r0.extend(Array2)
else
@index = i0
r0 = nil
end

node_cache[:array][start_index] = r0

r0
end

module String0
end

Expand Down
10 changes: 9 additions & 1 deletion app/models/user_segment_option_parser.treetop
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,21 @@ grammar UserSegmentOption
end

rule argument
space arg:(string / float / integer / boolean) space {
space arg:(string / float / integer / boolean / array) space {
def eval(env={})
arg.eval(env)
end
}
end

rule array
'[' arg:(string / float / integer / boolean) more:(',' val:(string / float / integer / boolean))* ']' {
def eval(env={})
[arg.eval(env)] + more.elements.collect{ |e| e.val.eval(env) }
end
}
end

rule string
('"' ('\"' / [^"])* '"' / "'" ("\\'" / [^'])* "'") {
def eval(env={})
Expand Down
2 changes: 2 additions & 0 deletions app/views/members/_operation_form_arguments.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
<% if builder.operation_arguments[idx] == :model -%>
<%= f.select("argument#{idx}", [["--Select %s--" / builder.operation_argument_names[idx], nil]] + UserSegment::FieldType.model_options(arg_options)) %>
<% elsif builder.operation_arguments[idx] == :array -%>
<%= f.check_boxes("argument#{idx}", UserSegment::FieldType.model_options(arg_options), :separator => '<br/>') %>
<% elsif arg_options[:options] -%>
<%= arg_options[:form_field] == 'radio_buttons' ? f.radio_buttons("argument#{idx}", arg_options[:options]) : f.select("argument#{idx}", arg_options[:options]) %>
<% elsif builder.operation_arguments[idx] == :boolean -%>
Expand Down
2 changes: 1 addition & 1 deletion app/views/members/builder_help.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ Ex: <b>created</b>.<u>since</u>(7, "days") - Will return all the user who where
<li><%= operation[:argument_names][idx] %> - <em><%= arg %></em>
<% if arg == :option -%>
<ul><li>
<%= operation[:argument_options][idx][:options].collect { |opt| opt = "#{opt[1]} '#{opt[0]}'" if opt.is_a?(Array); opt }.join(', ') if arg == :option %>
<%= operation[:argument_options][idx][:options].collect { |opt| opt = opt[0] if opt.is_a?(Array); opt }.join(', ') if arg == :option %>
</li></ul>
<% end -%>
</li>
Expand Down
4 changes: 2 additions & 2 deletions spec/models/user_segment/field_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@
@field = UserSegment::Field.new :field => 'created', :operation => 'before', :arguments => [1, 'days'], :child => {:field => 'registered', :operation => 'is', :arguments => [true]}
@field.valid?.should be_true

@field = UserSegment::Field.new :field => 'user_level', :operation => 'is', :arguments => [1]
@field = UserSegment::Field.new :field => 'user_level', :operation => 'is', :arguments => [[1]]
@field.valid?.should be_true

@field = UserSegment::Field.new :field => 'user_level', :operation => 'is', :arguments => [2]
@field = UserSegment::Field.new :field => 'user_level', :operation => 'is', :arguments => [[2]]
@field.valid?.should be_true
end

Expand Down
8 changes: 4 additions & 4 deletions spec/models/user_segment/filter_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -91,19 +91,19 @@

@operations = UserSegment::Filter.new
options = [
['not', {:field => 'created', :operation => 'since', :arguments => [3, 'days'], :child => nil}, {:field => 'user_level', :operation => 'is', :arguments => [1], :child => nil}],
['not', {:field => 'created', :operation => 'since', :arguments => [3, 'days'], :child => nil}, {:field => 'user_level', :operation => 'is', :arguments => [[1]], :child => nil}],
[nil, {:field => 'activated', :operation => 'is', :arguments => [true], :child => nil}]
]
code = <<-CODE
not created.since(3, "days") + user_level.is(1)
not created.since(3, "days") + user_level.is([1])
activated.is(true)
CODE
@operations.parse(code).should be_true
@operations.valid?.should == true
@operations.to_a.should == options
@operations.end_user_ids.length.should == 1
@operations.end_user_ids.include?(@user6.id).should be_true
@operations.to_expr.should == "not created.since(3, \"days\") + user_level.is(1)\nactivated.is(true)"
@operations.to_builder.should == {:operator => 'not', :condition => 'or', :field => 'created', :operation => 'since', :argument0 => 3, :argument1 => 'days', :child => {:field => 'user_level', :operation => 'is', :argument0 => 1, :condition => 'with', :child => {:operator => nil, :field => 'activated', :operation => 'is', :argument0 => true}}}
@operations.to_expr.should == "not created.since(3, \"days\") + user_level.is([1])\nactivated.is(true)"
@operations.to_builder.should == {:operator => 'not', :condition => 'or', :field => 'created', :operation => 'since', :argument0 => 3, :argument1 => 'days', :child => {:field => 'user_level', :operation => 'is', :argument0 => [1], :condition => 'with', :child => {:operator => nil, :field => 'activated', :operation => 'is', :argument0 => true}}}
end
end
12 changes: 12 additions & 0 deletions spec/models/user_segment_option_parser_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -125,4 +125,16 @@ def parse(text)
['not', {:field => 'test', :operation => 'is', :arguments => [false], :child => nil}, {:field => 'product', :operation => 'purchased', :arguments => ['computer'], :child => {:field => 'created', :operation => 'since', :arguments => [1, 'days'], :child => nil}}]
]
end

it "should parse array values as arguments" do
code = <<-CODE
user_level.is([4,5,6])
CODE
parse(code).should == [[nil, {:field => 'user_level', :operation => 'is', :arguments => [[4,5,6]], :child => nil}]]

code = <<-CODE
user_level.is("days", [4,5,6], true, [1,2], 5)
CODE
parse(code).should == [[nil, {:field => 'user_level', :operation => 'is', :arguments => ["days", [4,5,6], true, [1,2], 5], :child => nil}]]
end
end

0 comments on commit 51dd05f

Please sign in to comment.