flextures 3.0.1 → 3.1.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.
@@ -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
-