sniff 0.0.4 → 0.0.5
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/sniff/database.rb +43 -18
- metadata +7 -8
- data/lib/sniff/timeframe.rb +0 -251
data/lib/sniff/database.rb
CHANGED
@@ -7,45 +7,60 @@ module Sniff
|
|
7
7
|
class Database
|
8
8
|
class << self
|
9
9
|
def init(local_root, options = {})
|
10
|
+
db_init options
|
11
|
+
earth_init(options[:earth])
|
12
|
+
|
10
13
|
environments = []
|
11
|
-
environments <<
|
14
|
+
environments << init_environment(local_root, options)
|
12
15
|
|
13
16
|
unless local_root == Sniff.root
|
14
|
-
environments <<
|
17
|
+
environments << init_environment(Sniff.root)
|
15
18
|
end
|
19
|
+
|
20
|
+
load_all_schemas
|
16
21
|
|
17
|
-
db_init options
|
18
22
|
environments.each { |e| e.populate_fixtures }
|
19
23
|
end
|
20
24
|
|
21
|
-
def
|
25
|
+
def define_schema(&blk)
|
26
|
+
schemas << blk
|
27
|
+
end
|
28
|
+
|
29
|
+
def schemas
|
30
|
+
@schemas = [] unless defined?(@schemas)
|
31
|
+
@schemas
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
def init_environment(root, options = {})
|
22
36
|
db = new root, options
|
23
37
|
db.init
|
24
38
|
db
|
25
39
|
end
|
26
40
|
|
27
41
|
def db_init(options)
|
28
|
-
ActiveRecord::Base.logger = Logger.new
|
29
|
-
|
30
|
-
|
31
|
-
earth_init(options[:earth])
|
42
|
+
ActiveRecord::Base.logger = Logger.new options[:sqllogdev]
|
43
|
+
ActiveRecord::Base.establish_connection :adapter => 'sqlite3',
|
44
|
+
:database => ':memory:'
|
32
45
|
end
|
33
46
|
|
34
47
|
def earth_init(domain)
|
48
|
+
domain ||= :none
|
35
49
|
Earth.init domain, :apply_schemas => true
|
36
50
|
end
|
37
51
|
|
38
|
-
def
|
39
|
-
|
40
|
-
|
41
|
-
end
|
42
|
-
|
43
|
-
def db_drop(db_file_path)
|
44
|
-
FileUtils.rm db_file_path if File.exists?(db_file_path)
|
45
|
-
end
|
52
|
+
def load_all_schemas
|
53
|
+
orig_std_out = STDOUT.clone
|
54
|
+
STDOUT.reopen File.open(File.join('/tmp', 'schema_output'), 'w')
|
46
55
|
|
47
|
-
|
48
|
-
|
56
|
+
ActiveRecord::Schema.define(:version => 1) do
|
57
|
+
ar_schema = self
|
58
|
+
Sniff::Database.schemas.each do |s|
|
59
|
+
ar_schema.instance_eval &s
|
60
|
+
end
|
61
|
+
end
|
62
|
+
ensure
|
63
|
+
STDOUT.reopen(orig_std_out)
|
49
64
|
end
|
50
65
|
end
|
51
66
|
|
@@ -69,6 +84,10 @@ module Sniff
|
|
69
84
|
@load_data
|
70
85
|
end
|
71
86
|
|
87
|
+
def schema_path
|
88
|
+
@schema_path ||= File.join(lib_path, 'db', 'schema.rb')
|
89
|
+
end
|
90
|
+
|
72
91
|
def fixtures_path
|
73
92
|
@fixtures_path ||= File.join(lib_path, 'db', 'fixtures')
|
74
93
|
end
|
@@ -79,9 +98,15 @@ module Sniff
|
|
79
98
|
|
80
99
|
def init
|
81
100
|
load_supporting_libs
|
101
|
+
read_schema
|
82
102
|
read_fixtures if load_data?
|
83
103
|
end
|
84
104
|
|
105
|
+
def read_schema
|
106
|
+
log "Reading schema #{schema_path}"
|
107
|
+
load(schema_path) if File.exist?(schema_path)
|
108
|
+
end
|
109
|
+
|
85
110
|
def read_fixtures
|
86
111
|
require 'active_record/fixtures'
|
87
112
|
log "Reading fixtures from #{fixtures_path}/**/*.{yml,csv}"
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sniff
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 21
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 5
|
10
|
+
version: 0.0.5
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Derek Kastner
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-07-
|
18
|
+
date: 2010-07-20 00:00:00 -04:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -189,12 +189,12 @@ dependencies:
|
|
189
189
|
requirements:
|
190
190
|
- - "="
|
191
191
|
- !ruby/object:Gem::Version
|
192
|
-
hash:
|
192
|
+
hash: 17
|
193
193
|
segments:
|
194
194
|
- 0
|
195
195
|
- 0
|
196
|
-
-
|
197
|
-
version: 0.0.
|
196
|
+
- 7
|
197
|
+
version: 0.0.7
|
198
198
|
requirement: *id011
|
199
199
|
- !ruby/object:Gem::Dependency
|
200
200
|
type: :development
|
@@ -375,7 +375,6 @@ files:
|
|
375
375
|
- lib/sniff/database.rb
|
376
376
|
- lib/sniff/emitter.rb
|
377
377
|
- lib/sniff/tasks.rb
|
378
|
-
- lib/sniff/timeframe.rb
|
379
378
|
- lib/test_support/db/fixtures/census_divisions.csv
|
380
379
|
- lib/test_support/db/fixtures/census_regions.csv
|
381
380
|
- lib/test_support/db/fixtures/climate_divisions.csv
|
data/lib/sniff/timeframe.rb
DELETED
@@ -1,251 +0,0 @@
|
|
1
|
-
# Encapsulates a timeframe between two dates. The dates provided to the class are always until the last date. That means
|
2
|
-
# that the last date is excluded.
|
3
|
-
#
|
4
|
-
# # from 2007-10-01 00:00:00.000 to 2007-10-31 23:59:59.999
|
5
|
-
# Timeframe.new(Date(2007,10,1), Date(2007,11,1))
|
6
|
-
# # and holds 31 days
|
7
|
-
# Timeframe.new(Date(2007,10,1), Date(2007,11,1)).days #=> 31
|
8
|
-
|
9
|
-
module Sniff
|
10
|
-
class Timeframe
|
11
|
-
attr_accessor :from, :to
|
12
|
-
|
13
|
-
# Creates a new instance of Timeframe. You can either pass a start and end Date or a Hash with named arguments,
|
14
|
-
# with the following options:
|
15
|
-
#
|
16
|
-
# <tt>:month</tt>: Start date becomes the first day of this month, and the end date becomes the first day of
|
17
|
-
# the next month. If no <tt>:year</tt> is specified, the current year is used.
|
18
|
-
# <tt>:year</tt>: Start date becomes the first day of this year, and the end date becomes the first day of the
|
19
|
-
# next year.
|
20
|
-
#
|
21
|
-
# Examples:
|
22
|
-
#
|
23
|
-
# Timeframe.new Date.new(2007, 2, 1), Date.new(2007, 4, 1) # February and March
|
24
|
-
# Timeframe.new :year => 2004 # The year 2004
|
25
|
-
# Timeframe.new :month => 4 # April
|
26
|
-
# Timeframe.new :year => 2004, :month => 2 # Feburary 2004
|
27
|
-
def initialize(*args)
|
28
|
-
options = args.extract_options!
|
29
|
-
|
30
|
-
if month = options[:month]
|
31
|
-
month = Date.parse(month).month if month.is_a? String
|
32
|
-
year = options[:year] || Time.zone.today.year
|
33
|
-
from = Date.new(year, month, 1)
|
34
|
-
to = from.next_month
|
35
|
-
elsif year = options[:year]
|
36
|
-
from = Date.new(year, 1, 1)
|
37
|
-
to = Date.new(year+1, 1, 1)
|
38
|
-
end
|
39
|
-
|
40
|
-
from ||= args.shift.andand.to_date
|
41
|
-
to ||= args.shift.andand.to_date
|
42
|
-
|
43
|
-
raise ArgumentError, "Please supply a start and end date, `#{args.map(&:inspect).to_sentence}' is not enough" if from.nil? or to.nil?
|
44
|
-
raise ArgumentError, "Start date #{from} should be earlier than end date #{to}" if from > to
|
45
|
-
raise ArgumentError, 'Timeframes that cross year boundaries are dangerous' unless options[:skip_year_boundary_crossing_check] or from.year == to.yesterday.year or from == to
|
46
|
-
|
47
|
-
@from, @to = from, to
|
48
|
-
end
|
49
|
-
|
50
|
-
def inspect
|
51
|
-
"<Timeframe(#{object_id}) #{days} days starting #{from} ending #{to}>"
|
52
|
-
end
|
53
|
-
|
54
|
-
# The number of days in the timeframe
|
55
|
-
#
|
56
|
-
# Timeframe.new(Date.new(2007, 11, 1), Date.new(2007, 12, 1)).days #=> 30
|
57
|
-
# Timeframe.new(:month => 1).days #=> 31
|
58
|
-
# Timeframe.new(:year => 2004).days #=> 366
|
59
|
-
def days
|
60
|
-
(to - from).to_i
|
61
|
-
end
|
62
|
-
|
63
|
-
# Returns a string representation of the timeframe
|
64
|
-
def to_s
|
65
|
-
if [from.day, from.month, to.day, to.month].uniq == [1]
|
66
|
-
from.year.to_s
|
67
|
-
elsif from.day == 1 and to.day == 1 and to.month - from.month == 1
|
68
|
-
"#{Date::MONTHNAMES[from.month]} #{from.year}"
|
69
|
-
else
|
70
|
-
"the period from #{from.strftime('%d %B')} to #{to.yesterday.strftime('%d %B %Y')}"
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
# Returns true when the date is included in this Timeframe
|
75
|
-
def include?(obj)
|
76
|
-
# puts "checking to see if #{date} is between #{from} and #{to}" if Emitter::DEBUG
|
77
|
-
case obj
|
78
|
-
when Date
|
79
|
-
(from...to).include?(obj)
|
80
|
-
when Time
|
81
|
-
# (from...to).include?(obj.to_date)
|
82
|
-
raise "this wasn't previously supported, but it could be"
|
83
|
-
when Timeframe
|
84
|
-
from <= obj.from and to >= obj.to
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
def proper_include?(other_timeframe)
|
89
|
-
raise ArgumentError, 'Proper inclusion only makes sense when testing other Timeframes' unless other_timeframe.is_a? Timeframe
|
90
|
-
(from < other_timeframe.from) and (to > other_timeframe.to)
|
91
|
-
end
|
92
|
-
|
93
|
-
# Returns true when this timeframe is equal to the other timeframe
|
94
|
-
def ==(other)
|
95
|
-
# puts "checking to see if #{self} is equal to #{other}" if Emitter::DEBUG
|
96
|
-
return false unless other.is_a?(Timeframe)
|
97
|
-
from == other.from and to == other.to
|
98
|
-
end
|
99
|
-
alias :eql? :==
|
100
|
-
|
101
|
-
# Calculates a hash value for the Timeframe, used for equality checking and Hash lookups.
|
102
|
-
# This needs to be an integer or else it won't use #eql?
|
103
|
-
def hash
|
104
|
-
from.hash + to.hash
|
105
|
-
end
|
106
|
-
alias :to_param :hash
|
107
|
-
|
108
|
-
# Returns an array of month-long subtimeframes
|
109
|
-
# TODO: rename to month_subtimeframes
|
110
|
-
def months
|
111
|
-
raise ArgumentError, "Please only provide whole-month timeframes to Timeframe#months" unless from.day == 1 and to.day == 1
|
112
|
-
raise ArgumentError, 'Timeframes that cross year boundaries are dangerous during Timeframe#months' unless from.year == to.yesterday.year
|
113
|
-
year = from.year # therefore this only works in the from year
|
114
|
-
(from.month..to.yesterday.month).map { |m| Timeframe.new :month => m, :year => year }
|
115
|
-
end
|
116
|
-
|
117
|
-
# Returns the relevant year as a Timeframe
|
118
|
-
def year
|
119
|
-
raise ArgumentError, 'Timeframes that cross year boundaries are dangerous during Timeframe#year' unless from.year == to.yesterday.year
|
120
|
-
Timeframe.new :year => from.year
|
121
|
-
end
|
122
|
-
|
123
|
-
# multiyear safe
|
124
|
-
def month_subtimeframes
|
125
|
-
(from.year..to.yesterday.year).map do |year|
|
126
|
-
(1..12).map do |month|
|
127
|
-
Timeframe.new(:year => year, :month => month) & self
|
128
|
-
end
|
129
|
-
end.flatten.compact
|
130
|
-
end
|
131
|
-
|
132
|
-
# multiyear safe
|
133
|
-
def full_month_subtimeframes
|
134
|
-
month_subtimeframes.map { |st| Timeframe.new(:year => st.from.year, :month => st.from.month) }
|
135
|
-
end
|
136
|
-
|
137
|
-
# multiyear safe
|
138
|
-
def year_subtimeframes
|
139
|
-
(from.year..to.yesterday.year).map do |year|
|
140
|
-
Timeframe.new(:year => year) & self
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
|
-
# multiyear safe
|
145
|
-
def full_year_subtimeframes
|
146
|
-
(from.year..to.yesterday.year).map do |year|
|
147
|
-
Timeframe.new :year => year
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
# multiyear safe
|
152
|
-
def ending_no_later_than(date)
|
153
|
-
if to < date
|
154
|
-
self
|
155
|
-
elsif from >= date
|
156
|
-
nil
|
157
|
-
else
|
158
|
-
Timeframe.multiyear from, date
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
# Returns a timeframe representing the intersection of the timeframes
|
163
|
-
def &(other_timeframe)
|
164
|
-
this_timeframe = self
|
165
|
-
if other_timeframe == this_timeframe
|
166
|
-
this_timeframe
|
167
|
-
elsif this_timeframe.from > other_timeframe.from and this_timeframe.to < other_timeframe.to
|
168
|
-
this_timeframe
|
169
|
-
elsif other_timeframe.from > this_timeframe.from and other_timeframe.to < this_timeframe.to
|
170
|
-
other_timeframe
|
171
|
-
elsif this_timeframe.from >= other_timeframe.to or this_timeframe.to <= other_timeframe.from
|
172
|
-
nil
|
173
|
-
else
|
174
|
-
Timeframe.new [this_timeframe.from, other_timeframe.from].max, [this_timeframe.to, other_timeframe.to].min, :skip_year_boundary_crossing_check => true
|
175
|
-
end
|
176
|
-
end
|
177
|
-
|
178
|
-
# Returns a fraction of another Timeframe
|
179
|
-
def /(other_timeframe)
|
180
|
-
raise ArgumentError, 'You can only divide a Timeframe by another Timeframe' unless other_timeframe.is_a? Timeframe
|
181
|
-
self.days.to_f / other_timeframe.days.to_f
|
182
|
-
end
|
183
|
-
|
184
|
-
def crop(container)
|
185
|
-
raise ArgumentError, 'You can only crop a timeframe by another timeframe' unless container.is_a? Timeframe
|
186
|
-
self.class.new [from, container.from].max, [to, container.to].min
|
187
|
-
end
|
188
|
-
|
189
|
-
def gaps_left_by(*timeframes)
|
190
|
-
# remove extraneous timeframes
|
191
|
-
timeframes.reject! { |t| t.to <= from }
|
192
|
-
timeframes.reject! { |t| t.from >= to }
|
193
|
-
|
194
|
-
# crop timeframes
|
195
|
-
timeframes.map! { |t| t.crop self }
|
196
|
-
|
197
|
-
# remove proper subtimeframes
|
198
|
-
timeframes.reject! { |t| timeframes.detect { |u| u.proper_include? t } }
|
199
|
-
|
200
|
-
# escape
|
201
|
-
return [self] if timeframes.empty?
|
202
|
-
|
203
|
-
timeframes.sort! { |x, y| x.from <=> y.from }
|
204
|
-
|
205
|
-
timeframes.collect(&:to).unshift(from).ykk(timeframes.collect(&:from).push(to)) do |gap|
|
206
|
-
Timeframe.new(*gap) if gap[1] > gap[0]
|
207
|
-
end.compact
|
208
|
-
end
|
209
|
-
|
210
|
-
def covered_by?(*timeframes)
|
211
|
-
gaps_left_by(*timeframes).empty?
|
212
|
-
end
|
213
|
-
|
214
|
-
def last_year
|
215
|
-
self.class.new((from - 1.year), (to - 1.year))
|
216
|
-
end
|
217
|
-
|
218
|
-
class << self
|
219
|
-
def this_year
|
220
|
-
new :year => Time.now.year
|
221
|
-
end
|
222
|
-
|
223
|
-
def constrained_new(from, to, constraint)
|
224
|
-
raise ArgumentError, 'Need Date, Date, Timeframe as args' unless from.is_a? Date and to.is_a? Date and constraint.is_a? Timeframe
|
225
|
-
raise ArgumentError, "Start date #{from} should be earlier than end date #{to}" if from > to
|
226
|
-
if to <= constraint.from or from >= constraint.to
|
227
|
-
new constraint.from, constraint.from
|
228
|
-
elsif from.year == to.yesterday.year
|
229
|
-
new(from, to) & constraint
|
230
|
-
elsif from.year < constraint.from.year and constraint.from.year < to.yesterday.year
|
231
|
-
constraint
|
232
|
-
else
|
233
|
-
new [constraint.from, from].max, [constraint.to, to].min
|
234
|
-
end
|
235
|
-
end
|
236
|
-
|
237
|
-
def multiyear(from, to)
|
238
|
-
from = Date.parse(from) if from.is_a?(String)
|
239
|
-
to = Date.parse(to) if to.is_a?(String)
|
240
|
-
new from, to, :skip_year_boundary_crossing_check => true
|
241
|
-
end
|
242
|
-
|
243
|
-
# create a multiyear timeframe +/- number of years around today
|
244
|
-
def mid(number)
|
245
|
-
from = Time.zone.today - number.years
|
246
|
-
to = Time.zone.today + number.years
|
247
|
-
multiyear from, to
|
248
|
-
end
|
249
|
-
end
|
250
|
-
end
|
251
|
-
end
|