flog 2.2.0 → 2.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +1 -0
- data/.autotest +15 -0
- data/History.txt +22 -0
- data/Manifest.txt +1 -17
- data/bin/flog +1 -1
- data/lib/flog.rb +107 -103
- data/test/test_flog.rb +463 -1414
- metadata +26 -24
- metadata.gz.sig +0 -0
- data/gem_updater.rb +0 -161
- data/spec_fixtures/collection/bigger_example/acts/date_range.rb +0 -199
- data/spec_fixtures/collection/bigger_example/acts/range.rb +0 -391
- data/spec_fixtures/collection/bigger_example/association_extensions/date_ranged.rb +0 -11
- data/spec_fixtures/collection/bigger_example/association_extensions/ranged.rb +0 -13
- data/spec_fixtures/collection/bigger_example/reflection_extensions/ranged.rb +0 -50
- data/spec_fixtures/directory/bot_filter.rb +0 -70
- data/spec_fixtures/directory/bot_parser.rb +0 -79
- data/spec_fixtures/directory/bot_parser_format.rb +0 -23
- data/spec_fixtures/directory/bot_sender.rb +0 -46
- data/spec_fixtures/empty/empty.rb +0 -0
- data/spec_fixtures/simple/simple.rb +0 -191
- data/test/test_flog_command.rb +0 -343
- data/test/test_flog_integration.rb +0 -946
- data/test/test_helper.rb +0 -65
- data/unpack.rb +0 -22
- data/update_scores.rb +0 -245
@@ -1,391 +0,0 @@
|
|
1
|
-
module Centerstone #:nodoc:
|
2
|
-
module Acts #:nodoc:
|
3
|
-
module Range
|
4
|
-
|
5
|
-
def self.included(base) # :nodoc:
|
6
|
-
base.extend ClassMethods
|
7
|
-
unless ActiveRecord::Base.respond_to?(:end_dated_association_date)
|
8
|
-
class << ActiveRecord::Base
|
9
|
-
attr :end_dated_association_date, true
|
10
|
-
end
|
11
|
-
ActiveRecord::Base.end_dated_association_date = Proc.new { Time.now }
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
module InstanceMethods
|
16
|
-
def self.included(base) # :nodoc:
|
17
|
-
base.extend ClassMethods
|
18
|
-
end
|
19
|
-
|
20
|
-
%w{begin end}.each do |bound|
|
21
|
-
define_method "acts_as_range_#{bound}" do
|
22
|
-
send(self.class.send("acts_as_range_#{bound}_attr").to_sym)
|
23
|
-
end
|
24
|
-
|
25
|
-
define_method "acts_as_range_#{bound}=" do |val|
|
26
|
-
send((self.class.send("acts_as_range_#{bound}_attr").to_s + '=').to_sym, val)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
# convert this object into a range
|
31
|
-
# do something about nil/unspecified ends?
|
32
|
-
def to_range
|
33
|
-
begin_point = acts_as_range_begin
|
34
|
-
end_point = acts_as_range_end
|
35
|
-
|
36
|
-
begin_point ... end_point
|
37
|
-
end
|
38
|
-
|
39
|
-
# does the range for this object include the specified point?
|
40
|
-
def include?(point)
|
41
|
-
true if self.class.find(self.id, :on => point)
|
42
|
-
rescue
|
43
|
-
false
|
44
|
-
end
|
45
|
-
|
46
|
-
def contained_by?(range)
|
47
|
-
if range.respond_to?(:acts_as_range_begin)
|
48
|
-
# if this is really a range-ish object
|
49
|
-
if range.acts_as_range_begin and range.acts_as_range_end
|
50
|
-
# if it can actually be represented as a range
|
51
|
-
return contained_by?(range.to_range)
|
52
|
-
elsif range.acts_as_range_begin or range.acts_as_range_end
|
53
|
-
# if at least one bound is defined, compare that bound
|
54
|
-
if range.acts_as_range_begin
|
55
|
-
return false unless acts_as_range_begin
|
56
|
-
return acts_as_range_begin >= range.acts_as_range_begin
|
57
|
-
end
|
58
|
-
|
59
|
-
if range.acts_as_range_end
|
60
|
-
return false unless acts_as_range_end
|
61
|
-
return acts_as_range_end <= range.acts_as_range_end
|
62
|
-
end
|
63
|
-
else
|
64
|
-
# the given "range" has no bounds, thus it contains all
|
65
|
-
return true
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
# if the given range includes both bounds, it contains this object
|
70
|
-
# Note: Checking the end bound is a little tricky because of the exclusion choice with ranges (but not with acts_as_range)
|
71
|
-
range.include?(acts_as_range_begin) and (range.include?(acts_as_range_end) or ((range.last == acts_as_range_end) and (range.exclude_end? == to_range.exclude_end?)))
|
72
|
-
end
|
73
|
-
|
74
|
-
def containing?(target)
|
75
|
-
if target.respond_to?(:acts_as_range_begin)
|
76
|
-
# if this is really a range-ish object
|
77
|
-
# enough work has been done on contained_by?, so let's use that if we can
|
78
|
-
target.contained_by?(self)
|
79
|
-
else
|
80
|
-
if target.is_a?(::Range) # core Range class, not this Range module
|
81
|
-
if acts_as_range_begin and acts_as_range_end
|
82
|
-
# if this object can actually be represented as a range
|
83
|
-
# if this object's range includes both bounds of the given range, it contains that range
|
84
|
-
# Note: Checking the end bound is a little tricky because of the exclusion choice with ranges (but not with acts_as_range)
|
85
|
-
to_range.include?(target.first) and (to_range.include?(target.last) or ((to_range.last == target.last) and (to_range.exclude_end? == target.exclude_end?)))
|
86
|
-
elsif acts_as_range_begin or acts_as_range_end
|
87
|
-
# if at least one bound is defined, compare that bound
|
88
|
-
if acts_as_range_begin
|
89
|
-
return acts_as_range_begin <= target.first
|
90
|
-
end
|
91
|
-
|
92
|
-
if acts_as_range_end
|
93
|
-
# note the problem with checking the end bound above
|
94
|
-
return (acts_as_range_end > target.last or ((acts_as_range_end == target.last) and target.exclude_end?))
|
95
|
-
end
|
96
|
-
else
|
97
|
-
# this object's "range" has no bounds, thus it contains all
|
98
|
-
true
|
99
|
-
end
|
100
|
-
else
|
101
|
-
# this is a single point, so check it
|
102
|
-
begin_point = acts_as_range_begin || target
|
103
|
-
end_point = acts_as_range_end || target
|
104
|
-
|
105
|
-
(begin_point ... end_point).include?(target) or ((begin_point <= target) and !acts_as_range_end)
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|
109
|
-
alias_method :contains?, :containing?
|
110
|
-
|
111
|
-
def overlapping?(target)
|
112
|
-
# contained by target or containing target
|
113
|
-
return true if contained_by?(target) or containing?(target)
|
114
|
-
|
115
|
-
# or containing either bound
|
116
|
-
if target.respond_to?(:acts_as_range_begin)
|
117
|
-
containing_begin = containing?(target.acts_as_range_begin) if target.acts_as_range_begin
|
118
|
-
containing_end = containing?(target.acts_as_range_end) if target.acts_as_range_end
|
119
|
-
|
120
|
-
return (containing_begin or containing_end)
|
121
|
-
else
|
122
|
-
if target.is_a?(::Range) # core Range class, not this Range module
|
123
|
-
return (containing?(target.first) or containing?(target.last))
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
# if it got this far
|
128
|
-
false
|
129
|
-
end
|
130
|
-
alias_method :overlaps?, :overlapping?
|
131
|
-
|
132
|
-
def before?(point)
|
133
|
-
return false unless point
|
134
|
-
return false unless acts_as_range_end
|
135
|
-
|
136
|
-
if point.respond_to?(:acts_as_range_begin)
|
137
|
-
return before?(point.acts_as_range_begin)
|
138
|
-
end
|
139
|
-
|
140
|
-
acts_as_range_end < point
|
141
|
-
end
|
142
|
-
|
143
|
-
def after?(point)
|
144
|
-
return false unless point
|
145
|
-
return false unless acts_as_range_begin
|
146
|
-
|
147
|
-
if point.respond_to?(:acts_as_range_end)
|
148
|
-
return after?(point.acts_as_range_end)
|
149
|
-
end
|
150
|
-
|
151
|
-
acts_as_range_begin > point
|
152
|
-
end
|
153
|
-
|
154
|
-
module ClassMethods
|
155
|
-
|
156
|
-
%w{begin end}.each do |bound|
|
157
|
-
define_method "acts_as_range_#{bound}_attr" do
|
158
|
-
acts_as_range_configuration[bound.to_sym]
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
# add new options to Foo.find:
|
163
|
-
# :contain => t1 .. t2 - return objects whose spans contain this time interval
|
164
|
-
# :containing => t1 .. t2 - return objects whose spans contain this time interval
|
165
|
-
# :contained_by => t1 .. t2 - return objects whose spans are contained by this time interval
|
166
|
-
# :overlapping => t1 .. t2 - return objects whose spans overlap this time interval
|
167
|
-
# :on => t1 - return objects whose spans contain this time point
|
168
|
-
# :before => t1 - return objects whose spans are completed on or before this time point
|
169
|
-
# :after => t1 - return objects whose spans begin on or after this time point
|
170
|
-
#
|
171
|
-
# Note that each of the time interval methods will also take an object of this
|
172
|
-
# class and will use the time interval from that object as search parameters.
|
173
|
-
def find_with_range_restrictions(*args)
|
174
|
-
original_args = args.dup
|
175
|
-
options = extract_options_from_args!(args)
|
176
|
-
|
177
|
-
# which new arguments do we recognize, and which scoping methods do they use?
|
178
|
-
# eh, I don't like 'on' or 'contain'. Like the non-database instance methods
|
179
|
-
# above, 'containing' could handle both cases of range and point
|
180
|
-
method_map = { :contain => :with_containing_scope,
|
181
|
-
:containing => :with_containing_scope,
|
182
|
-
:contained_by => :with_contained_scope,
|
183
|
-
:overlapping => :with_overlapping_scope,
|
184
|
-
:on => nil,
|
185
|
-
:before => nil,
|
186
|
-
:after => nil }
|
187
|
-
|
188
|
-
# find objects with time intervals containing this time point
|
189
|
-
if options.has_key? :on
|
190
|
-
return with_containing_scope(options[:on], options[:on]) do
|
191
|
-
find_without_range_restrictions(*remove_args(original_args, method_map.keys))
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
|
-
# find objects with time intervals containing this time point
|
196
|
-
if options.has_key? :before
|
197
|
-
return with_before_scope(options[:before]) do
|
198
|
-
find_without_range_restrictions(*remove_args(original_args, method_map.keys))
|
199
|
-
end
|
200
|
-
end
|
201
|
-
|
202
|
-
# find objects with time intervals containing this time point
|
203
|
-
if options.has_key? :after
|
204
|
-
return with_after_scope(options[:after]) do
|
205
|
-
find_without_range_restrictions(*remove_args(original_args, method_map.keys))
|
206
|
-
end
|
207
|
-
end
|
208
|
-
|
209
|
-
# otherwise, find objects with time intervals matching this range
|
210
|
-
method_map.keys.each do |kind|
|
211
|
-
if options.has_key? kind
|
212
|
-
x = ranged_lookup(options[kind]) do |start, stop|
|
213
|
-
self.send(method_map[kind], start, stop) do
|
214
|
-
find_without_range_restrictions(*remove_args(original_args, method_map.keys))
|
215
|
-
end
|
216
|
-
end
|
217
|
-
# Patch for find :first, :conditions => 'impossible'
|
218
|
-
# Could be cleaner, but this handles it
|
219
|
-
return x == [nil] ? nil : x
|
220
|
-
end
|
221
|
-
end
|
222
|
-
|
223
|
-
# otherwise, find objects with time intervals active now
|
224
|
-
if acts_as_range_configuration[:end_dated]
|
225
|
-
with_current_time_scope { find_without_range_restrictions(*original_args) }
|
226
|
-
else
|
227
|
-
find_without_range_restrictions(*original_args)
|
228
|
-
end
|
229
|
-
end
|
230
|
-
|
231
|
-
def count_with_range_restrictions(*args)
|
232
|
-
if acts_as_range_configuration[:end_dated]
|
233
|
-
with_current_time_scope { count_without_range_restrictions(*args) }
|
234
|
-
else
|
235
|
-
count_without_range_restrictions(*args)
|
236
|
-
end
|
237
|
-
end
|
238
|
-
|
239
|
-
def calculate_with_range_restrictions(*args)
|
240
|
-
if acts_as_range_configuration[:end_dated]
|
241
|
-
with_current_time_scope { calculate_without_range_restrictions(*args) }
|
242
|
-
else
|
243
|
-
calculate_without_range_restrictions(*args)
|
244
|
-
end
|
245
|
-
end
|
246
|
-
|
247
|
-
# break out an args list, add in new options, return a new args list
|
248
|
-
def add_args(args, added)
|
249
|
-
args << extract_options_from_args!(args).merge(added)
|
250
|
-
end
|
251
|
-
|
252
|
-
protected
|
253
|
-
|
254
|
-
# break out an args list, remove specified options, return a new args list
|
255
|
-
def remove_args(args, removed)
|
256
|
-
options = extract_options_from_args!(args)
|
257
|
-
removed.each {|k| options.delete(k)}
|
258
|
-
args << options
|
259
|
-
args.last.keys.length > 0 ? args : args.first
|
260
|
-
end
|
261
|
-
|
262
|
-
# provide for lookups on a date range /or/ an acts_as_range object (filtering object out)
|
263
|
-
def ranged_lookup(obj)
|
264
|
-
filter_object = obj.respond_to?(:acts_as_range_begin)
|
265
|
-
start, stop = filter_object ? [obj.acts_as_range_begin, obj.acts_as_range_end] : [obj.first, obj.last]
|
266
|
-
result = yield(start, stop)
|
267
|
-
filter_object ? (Set.new(result) - Set.new([obj])).to_a : result
|
268
|
-
end
|
269
|
-
|
270
|
-
# find objects with intervals including the current time
|
271
|
-
def with_current_time_scope(&block)
|
272
|
-
t = ActiveRecord::Base.end_dated_association_date.call
|
273
|
-
if t.respond_to? :first
|
274
|
-
with_overlapping_scope(t.first, t.last, &block)
|
275
|
-
else
|
276
|
-
with_containing_scope(t, t, &block)
|
277
|
-
end
|
278
|
-
end
|
279
|
-
|
280
|
-
# find objects which are entirely before the specified time
|
281
|
-
def with_before_scope(t, &block)
|
282
|
-
with_scope({:find => { :conditions => ["(#{table_name}.#{acts_as_range_end_attr} is not null and #{table_name}.#{acts_as_range_end_attr} < ?)", t ] } }, :merge, &block)
|
283
|
-
end
|
284
|
-
|
285
|
-
# find objects which are entirely after the specified time
|
286
|
-
def with_after_scope(t, &block)
|
287
|
-
with_scope({:find => { :conditions => ["(#{table_name}.#{acts_as_range_begin_attr} is not null and #{table_name}.#{acts_as_range_begin_attr} > ?)", t ] } }, :merge, &block)
|
288
|
-
end
|
289
|
-
|
290
|
-
# find objects with intervals contained by the interval t1 .. t2
|
291
|
-
def with_contained_scope(t1, t2, &block)
|
292
|
-
conditions = []
|
293
|
-
args = []
|
294
|
-
|
295
|
-
if t1.nil?
|
296
|
-
if t2.nil?
|
297
|
-
conditions << "(1=1)"
|
298
|
-
else
|
299
|
-
conditions << "(#{table_name}.#{acts_as_range_end_attr} is not NULL and #{table_name}.#{acts_as_range_end_attr} < ?)"
|
300
|
-
args << t2
|
301
|
-
end
|
302
|
-
elsif t2.nil?
|
303
|
-
conditions << "(#{table_name}.#{acts_as_range_begin_attr} is not NULL and #{table_name}.#{acts_as_range_begin_attr} >= ?)"
|
304
|
-
args << t1
|
305
|
-
else
|
306
|
-
conditions << "(#{table_name}.#{acts_as_range_begin_attr} is not NULL and #{table_name}.#{acts_as_range_begin_attr} >= ?)"
|
307
|
-
args << t1
|
308
|
-
conditions << "(#{table_name}.#{acts_as_range_end_attr} is not NULL and #{table_name}.#{acts_as_range_end_attr} < ?)"
|
309
|
-
args << t2
|
310
|
-
end
|
311
|
-
|
312
|
-
conditions = ([ conditions.join(' AND ') ] << args).flatten
|
313
|
-
with_scope({:find => { :conditions => conditions } }, :merge, &block)
|
314
|
-
end
|
315
|
-
|
316
|
-
# find objects with intervals containing the interval t1 .. t2
|
317
|
-
def with_containing_scope(t1, t2, &block)
|
318
|
-
conditions = []
|
319
|
-
args = []
|
320
|
-
|
321
|
-
if t1.nil?
|
322
|
-
conditions << "(#{table_name}.#{acts_as_range_begin_attr} is NULL)"
|
323
|
-
else
|
324
|
-
conditions << "(#{table_name}.#{acts_as_range_begin_attr} <= ? or #{table_name}.#{acts_as_range_begin_attr} IS NULL)"
|
325
|
-
args << t1
|
326
|
-
end
|
327
|
-
|
328
|
-
if t2.nil?
|
329
|
-
conditions << "(#{table_name}.#{acts_as_range_end_attr} is NULL)"
|
330
|
-
else
|
331
|
-
conditions << "(#{table_name}.#{acts_as_range_end_attr} > ? or #{table_name}.#{acts_as_range_end_attr} IS NULL)"
|
332
|
-
args << t2
|
333
|
-
end
|
334
|
-
|
335
|
-
conditions = ([ conditions.join(' AND ') ] << args).flatten
|
336
|
-
with_scope({:find => { :conditions => conditions } }, :merge, &block)
|
337
|
-
end
|
338
|
-
|
339
|
-
# find objects with intervals overlapping the interval t1 .. t2
|
340
|
-
def with_overlapping_scope(t1, t2, &block)
|
341
|
-
[with_containing_scope(t1, t1, &block)].flatten | [with_containing_scope(t2, t2, &block)].flatten | [with_contained_scope(t1, t2, &block)].flatten
|
342
|
-
end
|
343
|
-
end
|
344
|
-
end
|
345
|
-
|
346
|
-
module ClassMethods
|
347
|
-
def acts_as_range(options = {})
|
348
|
-
return if acts_as_range? # don't let this be done twice
|
349
|
-
class_inheritable_reader :acts_as_range_configuration
|
350
|
-
raise "options must be a Hash" unless options.is_a?(Hash)
|
351
|
-
|
352
|
-
acts_as_range_configure_class({ :begin => :begin, :end => :end }.update(options))
|
353
|
-
end
|
354
|
-
|
355
|
-
def acts_as_range?
|
356
|
-
included_modules.include?(InstanceMethods)
|
357
|
-
end
|
358
|
-
|
359
|
-
# ensure that the beginning of the interval does not follow its end
|
360
|
-
def validates_interval
|
361
|
-
configuration = { :message => "#{acts_as_range_configuration[:begin].to_s.humanize} must be before #{acts_as_range_configuration[:end].to_s.humanize}.", :on => [ :save, :update ] }
|
362
|
-
configuration[:on].each do |symbol|
|
363
|
-
send(validation_method(symbol)) do |record|
|
364
|
-
unless configuration[:if] && !evaluate_condition(configuration[:if], record)
|
365
|
-
start, stop = record.acts_as_range_begin, record.acts_as_range_end
|
366
|
-
unless start.nil? or stop.nil? or start <= stop
|
367
|
-
record.errors.add(acts_as_range_configuration[:begin], configuration[:message])
|
368
|
-
end
|
369
|
-
end
|
370
|
-
end
|
371
|
-
end
|
372
|
-
end
|
373
|
-
|
374
|
-
protected
|
375
|
-
|
376
|
-
def acts_as_range_configure_class(options = {})
|
377
|
-
include InstanceMethods
|
378
|
-
write_inheritable_attribute(:acts_as_range_configuration, options)
|
379
|
-
|
380
|
-
class << self
|
381
|
-
%w{find count calculate}.each do |method|
|
382
|
-
alias_method_chain method.to_sym, :range_restrictions
|
383
|
-
end
|
384
|
-
end
|
385
|
-
|
386
|
-
validates_interval
|
387
|
-
end
|
388
|
-
end
|
389
|
-
end
|
390
|
-
end
|
391
|
-
end
|
@@ -1,13 +0,0 @@
|
|
1
|
-
module Centerstone #:nodoc:
|
2
|
-
module AssociationExtensions
|
3
|
-
module Ranged
|
4
|
-
|
5
|
-
%w{before after containing contained_by overlapping}.each do |comparison|
|
6
|
-
define_method comparison do |target|
|
7
|
-
self.select { |x| x.send((comparison + '?').to_sym, target) }
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
@@ -1,50 +0,0 @@
|
|
1
|
-
module Centerstone #:nodoc:
|
2
|
-
module ReflectionExtensions
|
3
|
-
module Ranged
|
4
|
-
|
5
|
-
def self.included(base)
|
6
|
-
puts 'hello'
|
7
|
-
base.send(:include, InstanceMethods)
|
8
|
-
|
9
|
-
base.instance_eval do
|
10
|
-
alias_method_chain :initialize, :has_many_range_extension
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
module InstanceMethods
|
15
|
-
def initialize_with_has_many_range_extension(*args)
|
16
|
-
puts 'yo'
|
17
|
-
returning initialize_without_has_many_range_extension(*args) do
|
18
|
-
puts 'returning stuff'
|
19
|
-
if macro.to_s == 'has_many'
|
20
|
-
puts 'adding the extension'
|
21
|
-
add_has_many_range_extension
|
22
|
-
end
|
23
|
-
puts 'blah'
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
private
|
28
|
-
|
29
|
-
def add_has_many_range_extension
|
30
|
-
puts 'extension adding, hey'
|
31
|
-
puts 'bbbbb'
|
32
|
-
puts "target class [#{klass}]"
|
33
|
-
if klass.acts_as_range?
|
34
|
-
puts 'target acts as range'
|
35
|
-
extension = Centerstone::AssociationExtensions::Ranged
|
36
|
-
opts = options
|
37
|
-
|
38
|
-
opts[:extend] ||= []
|
39
|
-
opts[:extend] = [opts[:extend]].flatten
|
40
|
-
|
41
|
-
opts[:extend].push(extension) unless opts[:extend].include?(extension)
|
42
|
-
|
43
|
-
@options = opts
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|