sniff 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/lib/sniff/database.rb +43 -18
  2. metadata +7 -8
  3. data/lib/sniff/timeframe.rb +0 -251
@@ -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 << really_init(local_root, options)
14
+ environments << init_environment(local_root, options)
12
15
 
13
16
  unless local_root == Sniff.root
14
- environments << really_init(Sniff.root)
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 really_init(root, options = {})
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 nil
29
- connect
30
- db_create
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 connect
39
- ActiveRecord::Base.establish_connection :adapter => 'sqlite3',
40
- :database => ':memory:'
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
- def db_create
48
- ActiveRecord::Base.connection
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: 23
4
+ hash: 21
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 4
10
- version: 0.0.4
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-19 00:00:00 -04:00
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: 19
192
+ hash: 17
193
193
  segments:
194
194
  - 0
195
195
  - 0
196
- - 6
197
- version: 0.0.6
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
@@ -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