flog 2.2.0 → 2.3.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.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
|