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.
- checksums.yaml +7 -0
- data/.gitignore +48 -0
- data/Gemfile +8 -13
- data/Gemfile.lock +9 -12
- data/{README.ja.rdoc → README.ja.md} +81 -56
- data/README.md +156 -0
- data/Rakefile +1 -57
- data/flextures.gemspec +19 -71
- data/lib/flextures/flextures.rb +22 -24
- data/lib/flextures/flextures_base_config.rb +1 -2
- data/lib/flextures/flextures_command.rb +0 -1
- data/lib/flextures/flextures_dumper.rb +14 -15
- data/lib/flextures/flextures_extension_modules.rb +3 -5
- data/lib/flextures/flextures_factory.rb +5 -6
- data/lib/flextures/flextures_loader.rb +117 -85
- data/lib/flextures/rspec_flextures_support.rb +49 -13
- data/lib/flextures/testunit_flextures_support.rb +16 -8
- data/lib/flextures/version.rb +1 -2
- metadata +41 -35
- data/History.txt +0 -9
- data/README.rdoc +0 -133
- data/VERSION +0 -1
@@ -10,11 +10,9 @@ require 'flextures/flextures_factory'
|
|
10
10
|
|
11
11
|
module Flextures
|
12
12
|
# data loader
|
13
|
-
|
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
|
-
|
95
|
-
|
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
|
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
|
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
|
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
|
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
|
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("/").
|
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?
|
246
|
-
return ["#{file_path}.yml", :yml] if type.member?(:yml) and File.exist?
|
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
|
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.
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
27
|
-
|
28
|
-
|
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
|
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<< ->{
|
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
|
-
|
35
|
+
flextures_loader.set_options(options)
|
27
36
|
}
|
28
37
|
context.teardown_blocks<< -> {
|
29
|
-
|
38
|
+
flextures_loader.delete_options
|
30
39
|
}
|
31
40
|
end
|
32
41
|
end
|
33
42
|
end
|
34
43
|
end
|
35
|
-
|