fluent_conditions 0.0.2
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/lib/fluent_conditions.rb +150 -0
- data/spec/fluent_conditions/builder_spec.rb +240 -0
- data/spec/fluent_conditions/fluent_conditions_spec.rb +84 -0
- data/spec/spec_helper.rb +1 -0
- metadata +50 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
module FluentConditions
|
|
2
|
+
|
|
3
|
+
def self.included(base)
|
|
4
|
+
base.instance_variable_set(:@builder, Class.new(Builder))
|
|
5
|
+
|
|
6
|
+
base.class_eval do
|
|
7
|
+
include InstanceMethods
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
base.extend ClassMethods
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
module InstanceMethods
|
|
14
|
+
def is
|
|
15
|
+
self.class.instance_variable_get(:@builder).new(self, :positive)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def is_not
|
|
19
|
+
self.class.instance_variable_get(:@builder).new(self, :negative)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
module ClassMethods
|
|
24
|
+
def fluent(field, options = {})
|
|
25
|
+
builder = instance_variable_get(:@builder)
|
|
26
|
+
|
|
27
|
+
if options.include?(:values)
|
|
28
|
+
options[:values].each do |value|
|
|
29
|
+
builder.class_eval do
|
|
30
|
+
define_method(value) do
|
|
31
|
+
update_and_continue(instance_variable_get(:@object).send(field) == value)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
define_method("#{value}?") do
|
|
35
|
+
update_and_finish(instance_variable_get(:@object).send(field) == value)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
define_method("not_#{value}") do
|
|
39
|
+
update_and_continue(instance_variable_get(:@object).send(field) != value)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
define_method("not_#{value}?") do
|
|
43
|
+
update_and_finish(instance_variable_get(:@object).send(field) != value)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
elsif options.include?(:if)
|
|
48
|
+
field_name = options[:as]
|
|
49
|
+
condition_check = options[:if]
|
|
50
|
+
|
|
51
|
+
builder.class_eval do
|
|
52
|
+
define_method(field_name) do
|
|
53
|
+
update_and_continue(condition_check.call(instance_variable_get(:@object).send(field)))
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
define_method("#{field_name}?") do
|
|
57
|
+
update_and_finish(condition_check.call(instance_variable_get(:@object).send(field)))
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
define_method("not_#{field_name}") do
|
|
61
|
+
update_and_continue(!condition_check.call(instance_variable_get(:@object).send(field)))
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
define_method("not_#{field_name}?") do
|
|
65
|
+
update_and_finish(!condition_check.call(instance_variable_get(:@object).send(field)))
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
else
|
|
69
|
+
builder.class_eval do
|
|
70
|
+
define_method(field) do
|
|
71
|
+
update_and_continue(instance_variable_get(:@object).send(field))
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
define_method("#{field}?") do
|
|
75
|
+
update_and_finish(instance_variable_get(:@object).send(field))
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
define_method("not_#{field}") do
|
|
79
|
+
update_and_continue(!instance_variable_get(:@object).send(field))
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
define_method("not_#{field}?") do
|
|
83
|
+
update_and_finish(!instance_variable_get(:@object).send(field))
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
class Builder
|
|
92
|
+
def initialize(object, type)
|
|
93
|
+
@object = object
|
|
94
|
+
@type = type
|
|
95
|
+
@previous, @current, @big_or = true, true, false
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def or
|
|
99
|
+
@or_flag = true
|
|
100
|
+
self
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def OR
|
|
104
|
+
@big_or = @big_or || result
|
|
105
|
+
@big_or_flag = true
|
|
106
|
+
@previous, @current = true, true
|
|
107
|
+
self
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def and
|
|
111
|
+
self
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
private
|
|
115
|
+
|
|
116
|
+
def update_and_continue(field_value)
|
|
117
|
+
update_result(field_value)
|
|
118
|
+
self
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def update_and_finish(field_value)
|
|
122
|
+
update_result(field_value)
|
|
123
|
+
end_result
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def update_result(field_value)
|
|
127
|
+
if @or_flag
|
|
128
|
+
@current = @current || field_value
|
|
129
|
+
@or_flag = false
|
|
130
|
+
else
|
|
131
|
+
@previous, @current = @previous && @current, field_value
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def end_result
|
|
136
|
+
if @big_or_flag
|
|
137
|
+
return (@big_or || result) if @type == :positive
|
|
138
|
+
return !(@big_or || result) if @type == :negative
|
|
139
|
+
end
|
|
140
|
+
return result if @type == :positive
|
|
141
|
+
return !result if @type == :negative
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def result
|
|
145
|
+
@previous && @current
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module FluentConditions
|
|
4
|
+
|
|
5
|
+
describe Builder do
|
|
6
|
+
|
|
7
|
+
describe "checking simple boolean conditions" do
|
|
8
|
+
before(:each) do
|
|
9
|
+
clazz = Class.new do
|
|
10
|
+
include FluentConditions
|
|
11
|
+
attr_accessor :admin
|
|
12
|
+
fluent :admin
|
|
13
|
+
end
|
|
14
|
+
@obj = clazz.new
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "should respond to added methods" do
|
|
18
|
+
@obj.is.should respond_to(:admin)
|
|
19
|
+
@obj.is.should respond_to(:admin?)
|
|
20
|
+
@obj.is.should respond_to(:not_admin)
|
|
21
|
+
@obj.is.should respond_to(:not_admin?)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it "should check for admin user if it's admin or not" do
|
|
25
|
+
@obj.admin = true
|
|
26
|
+
@obj.is.admin?.should be_true
|
|
27
|
+
@obj.is.not_admin?.should be_false
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "should check for non admin user if it's admin or not" do
|
|
31
|
+
@obj.admin = false
|
|
32
|
+
@obj.is.admin?.should be_false
|
|
33
|
+
@obj.is.not_admin?.should be_true
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it "should treat nil as false value" do
|
|
37
|
+
@obj.admin = nil
|
|
38
|
+
@obj.is.admin?.should be_false
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "should check negative condition" do
|
|
42
|
+
@obj.admin = false
|
|
43
|
+
@obj.is_not.admin?.should be_true
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
describe "more than one condition" do
|
|
48
|
+
before(:each) do
|
|
49
|
+
clazz = Class.new do
|
|
50
|
+
include FluentConditions
|
|
51
|
+
attr_accessor :good, :bad
|
|
52
|
+
fluent :good
|
|
53
|
+
fluent :bad
|
|
54
|
+
end
|
|
55
|
+
@obj = clazz.new
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it "should check two true conditions" do
|
|
59
|
+
@obj.good = true
|
|
60
|
+
@obj.bad = true
|
|
61
|
+
@obj.is.good.bad?.should be_true
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
it "should check two true/false conditions" do
|
|
65
|
+
@obj.good = true
|
|
66
|
+
@obj.bad = false
|
|
67
|
+
@obj.is.good.bad?.should be_false
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it "should check two false conditions" do
|
|
71
|
+
@obj.good = false
|
|
72
|
+
@obj.bad = false
|
|
73
|
+
@obj.is.good.bad?.should be_false
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
describe "with or" do
|
|
78
|
+
before(:each) do
|
|
79
|
+
clazz = Class.new do
|
|
80
|
+
include FluentConditions
|
|
81
|
+
attr_accessor :good, :bad
|
|
82
|
+
fluent :good
|
|
83
|
+
fluent :bad
|
|
84
|
+
end
|
|
85
|
+
@obj = clazz.new
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it "should check two true conditions" do
|
|
89
|
+
@obj.good = true
|
|
90
|
+
@obj.bad = true
|
|
91
|
+
@obj.is.good.or.bad?.should be_true
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
it "should check two true/false conditions" do
|
|
95
|
+
@obj.good = true
|
|
96
|
+
@obj.bad = false
|
|
97
|
+
@obj.is.good.or.bad?.should be_true
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
it "should check two false conditions" do
|
|
101
|
+
@obj.good = false
|
|
102
|
+
@obj.bad = false
|
|
103
|
+
@obj.is.good.or.bad?.should be_false
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
describe "complex conditions" do
|
|
108
|
+
before(:each) do
|
|
109
|
+
clazz = Class.new do
|
|
110
|
+
include FluentConditions
|
|
111
|
+
attr_accessor :good, :bad, :ugly
|
|
112
|
+
fluent :good
|
|
113
|
+
fluent :bad
|
|
114
|
+
fluent :ugly
|
|
115
|
+
end
|
|
116
|
+
@obj = clazz.new
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
it "should pass them all" do
|
|
120
|
+
@obj.good = true
|
|
121
|
+
@obj.bad = false
|
|
122
|
+
@obj.ugly = true
|
|
123
|
+
|
|
124
|
+
@obj.is.good.bad.ugly?.should be_false
|
|
125
|
+
@obj.is.good.ugly.bad?.should be_false
|
|
126
|
+
@obj.is.good.bad.or.ugly?.should be_true
|
|
127
|
+
@obj.is.good.or.bad.and.ugly?.should be_true
|
|
128
|
+
@obj.is.good.ugly.or.bad?.should be_true
|
|
129
|
+
|
|
130
|
+
@obj.is.bad.good.ugly?.should be_false
|
|
131
|
+
@obj.is.bad.ugly.good?.should be_false
|
|
132
|
+
@obj.is.bad.and.good.or.ugly?.should be_false
|
|
133
|
+
@obj.is.bad.ugly.or.good?.should be_false
|
|
134
|
+
@obj.is.bad.or.good.and.ugly?.should be_true
|
|
135
|
+
|
|
136
|
+
@obj.is.ugly.good.bad?.should be_false
|
|
137
|
+
@obj.is.ugly.bad.good?.should be_false
|
|
138
|
+
@obj.is.ugly.or.good.and.bad?.should be_false
|
|
139
|
+
@obj.is.ugly.good.and.bad?.should be_false
|
|
140
|
+
@obj.is.ugly.good.or.bad?.should be_true
|
|
141
|
+
|
|
142
|
+
@obj.is_not.good.bad.and.ugly?.should be_true
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
describe "when values were defined" do
|
|
147
|
+
before(:each) do
|
|
148
|
+
clazz = Class.new do
|
|
149
|
+
include FluentConditions
|
|
150
|
+
attr_accessor :color
|
|
151
|
+
fluent :color, :values => [:red, :green]
|
|
152
|
+
end
|
|
153
|
+
@product = clazz.new
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
it "should respond to accesor methods" do
|
|
157
|
+
@product.is.should respond_to(:red)
|
|
158
|
+
@product.is.should respond_to(:green)
|
|
159
|
+
@product.is.should respond_to(:not_red)
|
|
160
|
+
@product.is.should respond_to(:not_green)
|
|
161
|
+
|
|
162
|
+
@product.is.should respond_to(:red?)
|
|
163
|
+
@product.is.should respond_to(:green?)
|
|
164
|
+
@product.is.should respond_to(:not_red?)
|
|
165
|
+
@product.is.should respond_to(:not_green?)
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
it "should check condition by value" do
|
|
169
|
+
@product.color = :red
|
|
170
|
+
|
|
171
|
+
@product.is.red?.should be_true
|
|
172
|
+
@product.is.green?.should be_false
|
|
173
|
+
@product.is.red.and.green?.should be_false
|
|
174
|
+
@product.is.red.or.green?.should be_true
|
|
175
|
+
|
|
176
|
+
@product.is.not_red?.should be_false
|
|
177
|
+
@product.is.not_green?.should be_true
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
describe "when condition check defined by user" do
|
|
182
|
+
before(:each) do
|
|
183
|
+
clazz = Class.new do
|
|
184
|
+
include FluentConditions
|
|
185
|
+
attr_accessor :length
|
|
186
|
+
fluent :length, :as => :long, :if => proc { |length| length >= 500 }
|
|
187
|
+
fluent :length, :as => :short, :if => proc { |length| length < 500 }
|
|
188
|
+
end
|
|
189
|
+
@post = clazz.new
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
it "should respond to new methods" do
|
|
193
|
+
@post.is.should respond_to(:long)
|
|
194
|
+
@post.is.should respond_to(:not_long)
|
|
195
|
+
@post.is.should respond_to(:long?)
|
|
196
|
+
@post.is.should respond_to(:not_long?)
|
|
197
|
+
|
|
198
|
+
@post.is.should respond_to(:short)
|
|
199
|
+
@post.is.should respond_to(:not_short)
|
|
200
|
+
@post.is.should respond_to(:short?)
|
|
201
|
+
@post.is.should respond_to(:not_short?)
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
it "should check condition defined by user" do
|
|
205
|
+
@post.length = 600
|
|
206
|
+
|
|
207
|
+
@post.is.long?.should be_true
|
|
208
|
+
@post.is.not_long?.should be_false
|
|
209
|
+
@post.is.short?.should be_false
|
|
210
|
+
@post.is.short.or.long?.should be_true
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
describe "when big OR used" do
|
|
215
|
+
before(:each) do
|
|
216
|
+
clazz = Class.new do
|
|
217
|
+
include FluentConditions
|
|
218
|
+
attr_accessor :name, :color
|
|
219
|
+
fluent :name, :values => [:apple, :grass, :sky]
|
|
220
|
+
fluent :color, :values => [:red, :green, :blue]
|
|
221
|
+
end
|
|
222
|
+
@thing = clazz.new
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
it "should check conditions with OR" do
|
|
226
|
+
@thing.name = :apple
|
|
227
|
+
@thing.color = :red
|
|
228
|
+
|
|
229
|
+
@thing.is.green.grass.OR.red.apple?.should be_true
|
|
230
|
+
@thing.is.red.apple.OR.green.grass?.should be_true
|
|
231
|
+
@thing.is.blue.sky.OR.green.grass?.should be_false
|
|
232
|
+
|
|
233
|
+
@thing.is_not.red.apple.OR.green.grass?.should be_false
|
|
234
|
+
@thing.is_not.red.apple.OR.green.grass?.should be_false
|
|
235
|
+
@thing.is_not.blue.sky.OR.green.grass?.should be_true
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
end
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module FluentConditions
|
|
4
|
+
|
|
5
|
+
describe FluentConditions do
|
|
6
|
+
|
|
7
|
+
describe "when module indluded" do
|
|
8
|
+
before(:each) do
|
|
9
|
+
clazz = Class.new do
|
|
10
|
+
include FluentConditions
|
|
11
|
+
end
|
|
12
|
+
@obj = clazz.new
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it "should provide 'fluent' method now" do
|
|
16
|
+
@obj.class.should respond_to(:fluent)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "should provide 'is' method now" do
|
|
20
|
+
@obj.should respond_to(:is)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "should return Builder object when calling 'is'" do
|
|
24
|
+
@obj.is.should be_kind_of(Builder)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "should return new builder each time" do
|
|
28
|
+
@obj.is.object_id.should_not == @obj.is.object_id
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
describe "when included to different classes" do
|
|
33
|
+
before(:each) do
|
|
34
|
+
class User
|
|
35
|
+
include FluentConditions
|
|
36
|
+
attr_accessor :admin
|
|
37
|
+
fluent :admin
|
|
38
|
+
end
|
|
39
|
+
@user = User.new
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
describe "not in hierarchy" do
|
|
43
|
+
before(:each) do
|
|
44
|
+
class Color
|
|
45
|
+
include FluentConditions
|
|
46
|
+
attr_accessor :blue
|
|
47
|
+
fluent :blue
|
|
48
|
+
end
|
|
49
|
+
@color = Color.new
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it "should provide builders of different classes" do
|
|
53
|
+
@user.is.class.should_not == @color.is.class
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it "should not respond to other's builder accessors" do
|
|
57
|
+
@user.is.should_not respond_to(:blue)
|
|
58
|
+
@color.is.should_not respond_to(:admin)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
describe "in hierarchy" do
|
|
63
|
+
before(:each) do
|
|
64
|
+
class Employee < User
|
|
65
|
+
include FluentConditions
|
|
66
|
+
attr_accessor :manager
|
|
67
|
+
fluent :manager
|
|
68
|
+
end
|
|
69
|
+
@employee = Employee.new
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it "should provide builders of different classes" do
|
|
73
|
+
@user.is.class.should_not == @employee.is.class
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
it "should not respond to other's builder accessors" do
|
|
77
|
+
@user.is.should_not respond_to(:manager)
|
|
78
|
+
@employee.is.should_not respond_to(:admin)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
end
|
|
84
|
+
end
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require 'fluent_conditions'
|
metadata
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: fluent_conditions
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.2
|
|
5
|
+
prerelease:
|
|
6
|
+
platform: ruby
|
|
7
|
+
authors:
|
|
8
|
+
- pplcanfly
|
|
9
|
+
autorequire:
|
|
10
|
+
bindir: bin
|
|
11
|
+
cert_chain: []
|
|
12
|
+
date: 2011-09-18 00:00:00.000000000 +02:00
|
|
13
|
+
default_executable:
|
|
14
|
+
dependencies: []
|
|
15
|
+
description:
|
|
16
|
+
email:
|
|
17
|
+
executables: []
|
|
18
|
+
extensions: []
|
|
19
|
+
extra_rdoc_files: []
|
|
20
|
+
files:
|
|
21
|
+
- lib/fluent_conditions.rb
|
|
22
|
+
- spec/spec_helper.rb
|
|
23
|
+
- spec/fluent_conditions/fluent_conditions_spec.rb
|
|
24
|
+
- spec/fluent_conditions/builder_spec.rb
|
|
25
|
+
has_rdoc: true
|
|
26
|
+
homepage: http://github.com/pplcanfly/fluent_conditions
|
|
27
|
+
licenses: []
|
|
28
|
+
post_install_message:
|
|
29
|
+
rdoc_options: []
|
|
30
|
+
require_paths:
|
|
31
|
+
- lib
|
|
32
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
33
|
+
none: false
|
|
34
|
+
requirements:
|
|
35
|
+
- - ! '>='
|
|
36
|
+
- !ruby/object:Gem::Version
|
|
37
|
+
version: 1.8.7
|
|
38
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
39
|
+
none: false
|
|
40
|
+
requirements:
|
|
41
|
+
- - ! '>='
|
|
42
|
+
- !ruby/object:Gem::Version
|
|
43
|
+
version: '0'
|
|
44
|
+
requirements: []
|
|
45
|
+
rubyforge_project:
|
|
46
|
+
rubygems_version: 1.6.2
|
|
47
|
+
signing_key:
|
|
48
|
+
specification_version: 3
|
|
49
|
+
summary: Simplifies complex conditions
|
|
50
|
+
test_files: []
|