flextures 3.0.1 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -10,11 +10,9 @@ require 'flextures/flextures_factory'
10
10
 
11
11
  module Flextures
12
12
  # data loader
13
- module Loader
13
+ class Loader
14
14
  PARENT = Flextures
15
15
 
16
- @@option_cache = {}
17
-
18
16
  # column set default value
19
17
  COMPLETER = {
20
18
  binary:->{ 0 },
@@ -82,6 +80,79 @@ module Flextures
82
80
  },
83
81
  }
84
82
 
83
+ def initialize(*_)
84
+ # 読み込み状態を持っておく
85
+ @options = {}
86
+ @already_loaded_fixtures = {}
87
+ end
88
+
89
+ def loads(*fixtures)
90
+ # キャッシュが有効 ∧ 呼んだ事無いファイル
91
+ load_list = self.class.parse_flextures_options( @options, *fixtures)
92
+ load_list.sort(&self.class.loading_order).each do |params|
93
+ load(params)
94
+ end
95
+ end
96
+
97
+ def load(params)
98
+ return if cashable?(params) and loaded?(params)
99
+ @already_loaded_fixtures[params[:table]] = params
100
+ self.class.load(params)
101
+ end
102
+
103
+ def cashable?(params)
104
+ !!params[:cache]
105
+ end
106
+
107
+ def loaded?(params)
108
+ equal_table_data?(@already_loaded_fixtures[params[:table]], params)
109
+ end
110
+
111
+ # compare
112
+ def equal_table_data?(src,dst)
113
+ return false unless src.is_a?(Hash)
114
+ return false unless dst.is_a?(Hash)
115
+ (src.to_a - dst.to_a).empty?
116
+ end
117
+
118
+ # called by Rspec or Should
119
+ # set options
120
+ # @params [Hash] options exmple : { cashe: true, dir: "models/users" }
121
+ def set_options( options )
122
+ @options.merge!(options)
123
+ @options
124
+ end
125
+
126
+ # called by Rspec or Should after filter
127
+ # reflesh options
128
+ def delete_options
129
+ @options = {}
130
+ end
131
+
132
+ # return current option status
133
+ # @return [Hash] current option status
134
+ def flextures_options
135
+ @options
136
+ end
137
+
138
+ # parse flextures function arguments
139
+ # @params [Hash] fixtures function arguments
140
+ # @return [Array] formatted load options
141
+ def self.parse_flextures_options( base_options, *fixtures )
142
+ options = {}
143
+ options = fixtures.shift if fixtures.size > 1 and fixtures.first.is_a?(Hash)
144
+
145
+ options[:dir] = self.parse_controller_option( options ) if options[:controller]
146
+ options[:dir] = self.parse_model_options( options ) if options[:model]
147
+
148
+ # :all value load all loadable fixtures
149
+ fixtures = Flextures::deletable_tables if fixtures.size==1 and :all == fixtures.first
150
+ last_hash = fixtures.last.is_a?(Hash) ? fixtures.pop : {}
151
+ load_hash = fixtures.reduce({}){ |h,name| h[name.to_sym] = name.to_s; h } # if name is string is buged
152
+ load_hash.merge!(last_hash)
153
+ load_hash.map { |k,v| { table: k, file: v, loader: :fun }.merge(base_options).merge(options) }
154
+ end
155
+
85
156
  # load fixture datas
86
157
  #
87
158
  # example:
@@ -90,9 +161,9 @@ module Flextures
90
161
  # flextures :users => :users2 # :table_name => :file_name
91
162
  #
92
163
  # @params [Hash] fixtures load table data
93
- def self.flextures *fixtures
94
- load_list = parse_flextures_options(*fixtures)
95
- load_list.sort(&self.loading_order).each{ |params| Loader::load params }
164
+ def self.flextures( *fixtures )
165
+ loader = Flextures::Loader::Instance.new
166
+ loader.loads(*fixtures)
96
167
  end
97
168
 
98
169
  # @return [Proc] order rule block (user Array#sort methd)
@@ -104,31 +175,11 @@ module Flextures
104
175
  }
105
176
  end
106
177
 
107
- # called by Rspec or Should
108
- # set options
109
- # @params [Hash] options exmple : { cashe: true, dir: "models/users" }
110
- def self.set_options options
111
- @@option_cache ||= {}
112
- @@option_cache.merge!(options)
113
- end
114
-
115
- # called by Rspec or Should after filter
116
- # reflesh options
117
- def self.delete_options
118
- @@option_cache = {}
119
- end
120
-
121
- # return current option status
122
- # @return [Hash] current option status
123
- def self.flextures_options
124
- @@option_cache
125
- end
126
-
127
178
  # load fixture data
128
179
  # fixture file prefer YAML to CSV
129
180
  # @params [Hash] format file load format(table name, file name, options...)
130
- def self.load format
131
- file_name, method = file_exist format
181
+ def self.load( format )
182
+ file_name, method = file_exist(format)
132
183
  if method
133
184
  send(method, format)
134
185
  else
@@ -138,46 +189,46 @@ module Flextures
138
189
 
139
190
  # load CSV data
140
191
  # @params [Hash] format file load format(table name, file name, options...)
141
- def self.csv format
192
+ def self.csv( format )
142
193
  type = :csv
143
- file_name, ext = file_exist format, [type]
144
- return unless self.file_loadable? format, file_name
145
- klass, filter = self.create_model_filter format, file_name, type
146
- self.load_csv format, klass, filter, file_name
194
+ file_name, ext = file_exist( format, [type] )
195
+ return unless self.file_loadable?( format, file_name )
196
+ klass, filter = self.create_model_filter( format, file_name, type )
197
+ self.load_csv( format, klass, filter, file_name )
147
198
  end
148
199
 
149
200
  # load YAML data
150
201
  # @params [Hash] format file load format( table: name, file: name, options...)
151
- def self.yml format
202
+ def self.yml( format )
152
203
  type = :yml
153
- file_name, ext = file_exist format, [type]
204
+ file_name, ext = file_exist( format, [type] )
154
205
 
155
- return unless self.file_loadable? format, file_name
206
+ return unless self.file_loadable?( format, file_name )
156
207
 
157
- klass, filter = self.create_model_filter format, file_name, type
158
- self.load_yml format, klass, filter, file_name
208
+ klass, filter = self.create_model_filter( format, file_name, type )
209
+ self.load_yml( format, klass, filter, file_name )
159
210
  end
160
211
 
161
- def self.load_csv format, klass, filter, file_name
162
- attributes = klass.columns.map &:name
212
+ def self.load_csv( format, klass, filter, file_name )
213
+ attributes = klass.columns.map(&:name)
163
214
  CSV.open( file_name ) do |csv|
164
215
  keys = csv.shift # active record column names
165
- warning "CSV", attributes, keys unless format[:silent]
216
+ warning( "CSV", attributes, keys ) unless format[:silent]
166
217
  csv.each do |values|
167
218
  h = values.extend(Extensions::Array).to_hash(keys)
168
- filter.call h
219
+ filter.call(h)
169
220
  end
170
221
  end
171
222
  file_name
172
223
  end
173
224
 
174
- def self.load_yml format, klass, filter, file_name
175
- yaml = YAML.load File.open(file_name)
225
+ def self.load_yml( format, klass, filter, file_name )
226
+ yaml = YAML.load( File.open(file_name) )
176
227
  return false unless yaml # if file is empty
177
- attributes = klass.columns.map &:name
228
+ attributes = klass.columns.map(&:name)
178
229
  yaml.each do |k,h|
179
- warning "YAML", attributes, h.keys unless format[:silent]
180
- filter.call h
230
+ warning( "YAML", attributes, h.keys ) unless format[:silent]
231
+ filter.call(h)
181
232
  end
182
233
  file_name
183
234
  end
@@ -186,7 +237,7 @@ module Flextures
186
237
  # load directroy is change
187
238
  # spec/fixtures/:controller_name/:action_name/
188
239
  # @return [String] directory path
189
- def self.parse_controller_option options
240
+ def self.parse_controller_option( options )
190
241
  controller_dir = ["controllers"]
191
242
  controller_dir<< options[:controller] if options[:controller]
192
243
  controller_dir<< options[:action] if options[:controller] and options[:action]
@@ -197,38 +248,20 @@ module Flextures
197
248
  # load directroy is change
198
249
  # spec/fixtures/:model_name/:method_name/
199
250
  # @return [String] directory path
200
- def self.parse_model_options options
251
+ def self.parse_model_options( options )
201
252
  model_dir = ["models"]
202
253
  model_dir<< options[:model] if options[:model]
203
254
  model_dir<< options[:method] if options[:model] and options[:method]
204
255
  File.join(*model_dir)
205
256
  end
206
257
 
207
- # parse flextures function arguments
208
- # @params [Hash] fixtures function arguments
209
- # @return [Array] formatted load options
210
- def self.parse_flextures_options *fixtures
211
- options = {}
212
- options = fixtures.shift if fixtures.size > 1 and fixtures.first.is_a?(Hash)
213
-
214
- options[:dir] = self.parse_controller_option( options ) if options[:controller]
215
- options[:dir] = self.parse_model_options( options ) if options[:model]
216
-
217
- # :all value load all loadable fixtures
218
- fixtures = Flextures::deletable_tables if fixtures.size==1 and :all == fixtures.first
219
- last_hash = fixtures.last.is_a?(Hash) ? fixtures.pop : {}
220
- load_hash = fixtures.inject({}){ |h,name| h[name.to_sym] = name.to_s; h } # if name is string is buged
221
- load_hash.merge!(last_hash)
222
- load_hash.map { |k,v| { table: k, file: v, loader: :fun }.merge(@@option_cache).merge(options) }
223
- end
224
-
225
258
  # example:
226
259
  # self.create_stair_list("foo/bar/baz")
227
260
  # return ["foo/bar/baz","foo/bar","foo",""]
228
- def self.stair_list dir, stair=true
261
+ def self.stair_list( dir, stair=true )
229
262
  return [dir.to_s] unless stair
230
263
  l = []
231
- dir.to_s.split("/").inject([]){ |a,d| a<< d; l.unshift(a.join("/")); a }
264
+ dir.to_s.split("/").reduce([]){ |a,d| a<< d; l.unshift(a.join("/")); a }
232
265
  l<< ""
233
266
  l
234
267
  end
@@ -236,43 +269,43 @@ module Flextures
236
269
  # parse format option and return load file info
237
270
  # @param [Hash] format load file format informations
238
271
  # @return [Array] [file_name, filt_type(:csv or :yml)]
239
- def self.file_exist format, type = [:csv,:yml]
272
+ def self.file_exist( format, type = [:csv,:yml] )
240
273
  table_name = format[:table].to_s
241
274
  file_name = (format[:file] || format[:table]).to_s
242
275
  base_dir_name = Flextures::Config.fixture_load_directory
243
276
  self.stair_list(format[:dir], format[:stair]).each do |dir|
244
277
  file_path = File.join( base_dir_name, dir, file_name )
245
- return ["#{file_path}.csv", :csv] if type.member?(:csv) and File.exist? "#{file_path}.csv"
246
- return ["#{file_path}.yml", :yml] if type.member?(:yml) and File.exist? "#{file_path}.yml"
278
+ return ["#{file_path}.csv", :csv] if type.member?(:csv) and File.exist?("#{file_path}.csv")
279
+ return ["#{file_path}.yml", :yml] if type.member?(:yml) and File.exist?("#{file_path}.yml")
247
280
  end
248
281
  [ File.join(base_dir_name, "#{file_name}.csv"), nil ]
249
282
  end
250
283
 
251
284
  # file load check
252
285
  # @return [Bool] lodable is 'true'
253
- def self.file_loadable? format, file_name
254
- return unless File.exist? file_name
286
+ def self.file_loadable?( format, file_name )
287
+ return unless File.exist?( file_name )
255
288
  puts "try loading #{file_name}" if !format[:silent] and ![:fun].include?(format[:loader])
256
289
  true
257
290
  end
258
291
 
259
292
  # print warinig message that lack or not exist colum names
260
- def self.warning format, attributes, keys
293
+ def self.warning( format, attributes, keys )
261
294
  (attributes-keys).each { |name| puts "Warning: #{format} colum is missing! [#{name}]" }
262
295
  (keys-attributes).each { |name| puts "Warning: #{format} colum is left over! [#{name}]" }
263
296
  end
264
297
 
265
298
  # create filter and table info
266
- def self.create_model_filter format, file_name, type
299
+ def self.create_model_filter( format, file_name, type )
267
300
  table_name = format[:table].to_s
268
- klass = PARENT::create_model table_name
301
+ klass = PARENT::create_model( table_name )
269
302
  # if you use 'rails3_acts_as_paranoid' gem, that is not delete data 'delete_all' method
270
- klass.send (klass.respond_to?(:delete_all!) ? :delete_all! : :delete_all)
303
+ klass.send( klass.respond_to?(:delete_all!) ? :delete_all! : :delete_all )
271
304
 
272
305
  filter = ->(h){
273
- filter = create_filter klass, LoadFilter[table_name.to_sym], file_name, type, format
306
+ filter = create_filter( klass, LoadFilter[table_name.to_sym], file_name, type, format )
274
307
  o = klass.new
275
- o = filter.call o, h
308
+ o = filter.call( o, h )
276
309
  o.save( validate: false )
277
310
  o
278
311
  }
@@ -289,13 +322,13 @@ module Flextures
289
322
  # @params [Symbol] ext file type (:csv or :yml)
290
323
  # @params [Hash] options other options
291
324
  # @return [Proc] translate filter
292
- def self.create_filter klass, factory, filename, ext, options
325
+ def self.create_filter( klass, factory, filename, ext, options )
293
326
  columns = klass.columns
294
327
  # data translat array to hash
295
- column_hash = columns.inject({}) { |h,col| h[col.name] = col; h }
328
+ column_hash = columns.reduce({}) { |h,col| h[col.name] = col; h }
296
329
  lack_columns = columns.reject { |c| c.null and c.default }.map{ |o| o.name.to_sym }
297
330
  # default value shound not be null columns
298
- not_nullable_columns = columns.reject(&:null).map &:name
331
+ not_nullable_columns = columns.reject(&:null).map(&:name)
299
332
  strict_filter=->(o,h){
300
333
  # if value is not 'nil', value translate suitable form
301
334
  h.each{ |k,v| v.nil? || o[k] = (TRANSLATER[column_hash[k].type] && TRANSLATER[column_hash[k].type].call(v)) }
@@ -312,7 +345,7 @@ module Flextures
312
345
  h.select! { |k,v| column_hash[k] }
313
346
  strict_filter.call(o,h)
314
347
  # set default value if value is 'nil'
315
- not_nullable_columns.each{ |k| o[k].nil? && o[k] = (column_hash[k] && COMPLETER[column_hash[k].type] && COMPLETER[column_hash[k].type].call) }
348
+ not_nullable_columns.each { |k| o[k].nil? && o[k] = (column_hash[k] && COMPLETER[column_hash[k].type] && COMPLETER[column_hash[k].type].call) }
316
349
  # fill span values if column is not exist
317
350
  lack_columns.each { |k| o[k].nil? && o[k] = (column_hash[k] && COMPLETER[column_hash[k].type] && COMPLETER[column_hash[k].type].call) }
318
351
  o
@@ -321,4 +354,3 @@ module Flextures
321
354
  end
322
355
  end
323
356
  end
324
-
@@ -1,33 +1,63 @@
1
1
  # encoding: utf-8
2
2
 
3
+
4
+ module RSpec
5
+ module Rails
6
+ module SetupAndTeardownAdapter
7
+ extend ActiveSupport::Concern
8
+
9
+ module ClassMethods
10
+ def flextures_prepend_before(&block)
11
+ prepend_before(&block)
12
+ end
13
+
14
+ def flextures_before(&block)
15
+ before(&block)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+
3
22
  # flextures function use like fixtures method in RSpec
4
23
  module RSpec
5
24
  module Core
6
25
  module Hooks
7
26
  # load fixtture data
8
27
  # @params [Array] _ fixture file names
9
- def flextures *_
10
- before { Flextures::Loader::flextures *_ }
28
+ def flextures( *_ )
29
+ flextures_loader = create_or_get_flextures_loader(__method__)
30
+ flextures_before do
31
+ flextures_loader.loads( *_ )
32
+ end
33
+ end
34
+
35
+ # flexturesの読み出し
36
+ def create_or_get_flextures_loader(*_)
37
+ @@flextures_loader ||= Flextures::Loader.new(*_)
38
+ end
39
+
40
+ def flextures_get_options
41
+ @@flextures_loader
11
42
  end
12
43
 
13
44
  # delete table data
14
45
  # @params [Array] _ table names
15
- def flextures_delete *_
16
- before {
46
+ def flextures_delete( *_ )
47
+ flextures_loader = create_or_get_flextures_loader(__method__)
48
+ flextures_before do
17
49
  if _.empty?
18
50
  Flextures::init_tables
19
51
  else
20
- Flextures::delete_tables *_
52
+ Flextures::delete_tables( *_ )
21
53
  end
22
- }
54
+ end
23
55
  end
24
56
 
25
- def flextures_set_options options
26
- before do
27
- Flextures::Loader::set_options options
28
- end
29
- after do
30
- Flextures::Loader::delete_options
57
+ def flextures_set_options( options )
58
+ flextures_loader = create_or_get_flextures_loader(__method__)
59
+ flextures_prepend_before do
60
+ flextures_loader.set_options( options )
31
61
  end
32
62
  end
33
63
  end
@@ -53,6 +83,13 @@ module ActiveRecord
53
83
  def setup_fixtures
54
84
  Flextures::init_load
55
85
  setup_fixtures_bkup
86
+ set_transactional_filter_params
87
+ end
88
+
89
+ # nilで無い時は値をtransactional_filterが有効 
90
+ def set_transactional_filter_params
91
+ return if Flextures::Config.use_transactional_fixtures.nil?
92
+ self.use_transactional_fixtures = Flextures::Config.use_transactional_fixtures
56
93
  end
57
94
 
58
95
  alias :teardown_fixtures_bkup :teardown_fixtures
@@ -61,4 +98,3 @@ module ActiveRecord
61
98
  end
62
99
  end
63
100
  end
64
-
@@ -4,32 +4,40 @@
4
4
  module Shoulda
5
5
  module Context
6
6
  module ClassMethods
7
- def flextures *_
7
+ def create_or_get_flextures_loader
8
+ @flextures_loader ||= Flextures::Loader.new
9
+ end
10
+
11
+ def flextures( *_ )
12
+ flextures_loader = create_or_get_flextures_loader
13
+
8
14
  context = Shoulda::Context.current_context
9
- context.setup_blocks<< ->{ Flextures::Loader::flextures *_ }
15
+ context.setup_blocks<< ->{ flextures_loader.flextures(*_) }
10
16
  end
11
17
 
12
- def flextures_delete *_
18
+ def flextures_delete( *_ )
13
19
  context = Shoulda::Context.current_context
20
+
14
21
  context.setup_blocks<< -> {
15
22
  if _.empty?
16
23
  Flextures::init_tables
17
24
  else
18
- Flextures::delete_tables *_
25
+ Flextures::delete_tables(*_)
19
26
  end
20
27
  }
21
28
  end
22
29
 
23
- def flextures_set_options options={}
30
+ def flextures_set_options( options={} )
31
+ flextures_loader = create_or_get_flextures_loader
32
+
24
33
  context = Shoulda::Context.current_context
25
34
  context.setup_blocks<< -> {
26
- Flextures::Loader::set_options options
35
+ flextures_loader.set_options(options)
27
36
  }
28
37
  context.teardown_blocks<< -> {
29
- Flextures::Loader::delete_options
38
+ flextures_loader.delete_options
30
39
  }
31
40
  end
32
41
  end
33
42
  end
34
43
  end
35
-