sniff 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|