flextures 1.9.6 → 1.9.7
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.
- data/Gemfile +3 -8
- data/Gemfile.lock +8 -6
- data/Rakefile +2 -0
- data/VERSION +1 -2
- data/flextures.gemspec +11 -12
- data/lib/flextures.rb +2 -0
- data/lib/flextures/flextures.rb +0 -206
- data/lib/flextures/flextures_dumper.rb +129 -0
- data/lib/flextures/flextures_loader.rb +143 -0
- metadata +21 -20
data/Gemfile
CHANGED
@@ -1,13 +1,8 @@
|
|
1
1
|
source "http://rubygems.org"
|
2
|
-
# Add dependencies required to use your gem here.
|
3
|
-
# Example:
|
4
|
-
# gem "activesupport", ">= 2.3.5"
|
5
2
|
|
6
|
-
# Add dependencies to develop your gem here.
|
7
|
-
# Include everything needed to run rake, tests, features, etc.
|
8
3
|
group :development do
|
9
4
|
#gem "shoulda", ">= 0"
|
10
|
-
gem "bundler", "
|
11
|
-
gem "jeweler", "
|
12
|
-
gem "rcov", ">= 0"
|
5
|
+
gem "bundler", "1.1.3"
|
6
|
+
gem "jeweler", "1.8.3"
|
7
|
+
#gem "rcov", ">= 0"
|
13
8
|
end
|
data/Gemfile.lock
CHANGED
@@ -2,17 +2,19 @@ GEM
|
|
2
2
|
remote: http://rubygems.org/
|
3
3
|
specs:
|
4
4
|
git (1.2.5)
|
5
|
-
jeweler (1.
|
5
|
+
jeweler (1.8.3)
|
6
6
|
bundler (~> 1.0)
|
7
7
|
git (>= 1.2.5)
|
8
8
|
rake
|
9
|
-
|
10
|
-
|
9
|
+
rdoc
|
10
|
+
json (1.6.5)
|
11
|
+
rake (0.9.2.2)
|
12
|
+
rdoc (3.12)
|
13
|
+
json (~> 1.4)
|
11
14
|
|
12
15
|
PLATFORMS
|
13
16
|
ruby
|
14
17
|
|
15
18
|
DEPENDENCIES
|
16
|
-
bundler (
|
17
|
-
jeweler (
|
18
|
-
rcov
|
19
|
+
bundler (= 1.1.3)
|
20
|
+
jeweler (= 1.8.3)
|
data/Rakefile
CHANGED
@@ -32,6 +32,7 @@ Rake::TestTask.new(:test) do |test|
|
|
32
32
|
test.verbose = true
|
33
33
|
end
|
34
34
|
|
35
|
+
=begin
|
35
36
|
require 'rcov/rcovtask'
|
36
37
|
Rcov::RcovTask.new do |test|
|
37
38
|
test.libs << 'test'
|
@@ -39,6 +40,7 @@ Rcov::RcovTask.new do |test|
|
|
39
40
|
test.verbose = true
|
40
41
|
test.rcov_opts << '--exclude "gems/*"'
|
41
42
|
end
|
43
|
+
=end
|
42
44
|
|
43
45
|
task :default => :test
|
44
46
|
|
data/VERSION
CHANGED
@@ -1,2 +1 @@
|
|
1
|
-
1.9.
|
2
|
-
|
1
|
+
1.9.7
|
data/flextures.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "flextures"
|
8
|
-
s.version = "1.9.
|
8
|
+
s.version = "1.9.7"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["baban"]
|
12
|
-
s.date = "2012-
|
12
|
+
s.date = "2012-04-12"
|
13
13
|
s.description = "load and dump fixtures"
|
14
14
|
s.email = "babanba.n@gmail.com"
|
15
15
|
s.extra_rdoc_files = [
|
@@ -33,8 +33,10 @@ Gem::Specification.new do |s|
|
|
33
33
|
"lib/flextures/flextures.rake",
|
34
34
|
"lib/flextures/flextures.rb",
|
35
35
|
"lib/flextures/flextures_base_config.rb",
|
36
|
+
"lib/flextures/flextures_dumper.rb",
|
36
37
|
"lib/flextures/flextures_extension_modules.rb",
|
37
38
|
"lib/flextures/flextures_factory.rb",
|
39
|
+
"lib/flextures/flextures_loader.rb",
|
38
40
|
"lib/flextures/flextures_railtie.rb",
|
39
41
|
"lib/flextures/rspec_flextures_support.rb",
|
40
42
|
"lib/flextures/testunit_flextures_support.rb"
|
@@ -42,25 +44,22 @@ Gem::Specification.new do |s|
|
|
42
44
|
s.homepage = "http://github.com/baban/flextures"
|
43
45
|
s.licenses = ["MIT"]
|
44
46
|
s.require_paths = ["lib"]
|
45
|
-
s.rubygems_version = "1.8.
|
47
|
+
s.rubygems_version = "1.8.21"
|
46
48
|
s.summary = "load and dump fixtures"
|
47
49
|
|
48
50
|
if s.respond_to? :specification_version then
|
49
51
|
s.specification_version = 3
|
50
52
|
|
51
53
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
52
|
-
s.add_development_dependency(%q<bundler>, ["
|
53
|
-
s.add_development_dependency(%q<jeweler>, ["
|
54
|
-
s.add_development_dependency(%q<rcov>, [">= 0"])
|
54
|
+
s.add_development_dependency(%q<bundler>, ["= 1.1.3"])
|
55
|
+
s.add_development_dependency(%q<jeweler>, ["= 1.8.3"])
|
55
56
|
else
|
56
|
-
s.add_dependency(%q<bundler>, ["
|
57
|
-
s.add_dependency(%q<jeweler>, ["
|
58
|
-
s.add_dependency(%q<rcov>, [">= 0"])
|
57
|
+
s.add_dependency(%q<bundler>, ["= 1.1.3"])
|
58
|
+
s.add_dependency(%q<jeweler>, ["= 1.8.3"])
|
59
59
|
end
|
60
60
|
else
|
61
|
-
s.add_dependency(%q<bundler>, ["
|
62
|
-
s.add_dependency(%q<jeweler>, ["
|
63
|
-
s.add_dependency(%q<rcov>, [">= 0"])
|
61
|
+
s.add_dependency(%q<bundler>, ["= 1.1.3"])
|
62
|
+
s.add_dependency(%q<jeweler>, ["= 1.8.3"])
|
64
63
|
end
|
65
64
|
end
|
66
65
|
|
data/lib/flextures.rb
CHANGED
@@ -4,6 +4,8 @@ require 'flextures/flextures_base_config'
|
|
4
4
|
require 'flextures/flextures_extension_modules'
|
5
5
|
require 'flextures/flextures'
|
6
6
|
require 'flextures/flextures_factory'
|
7
|
+
require 'flextures/flextures_loader'
|
8
|
+
require 'flextures/flextures_dumper'
|
7
9
|
require 'flextures/flextures_railtie' if defined? Rails
|
8
10
|
require 'flextures/rspec_flextures_support' if defined? RSpec
|
9
11
|
require 'flextures/testunit_flextures_support' if defined? Test::Unit::TestCase
|
data/lib/flextures/flextures.rb
CHANGED
@@ -90,211 +90,5 @@ module Flextures
|
|
90
90
|
return->(name){ File.exists?("#{LOAD_DIR}#{name}.csv") or File.exists?("#{LOAD_DIR}#{name}.yml") }
|
91
91
|
end
|
92
92
|
end
|
93
|
-
|
94
|
-
# データを吐き出す処理をまとめる
|
95
|
-
module Dumper
|
96
|
-
PARENT = Flextures
|
97
|
-
|
98
|
-
TRANSLATER = {
|
99
|
-
binary:->(d){ d.to_i },
|
100
|
-
boolean:->(d){ (0==d || ""==d || !d) ? false : true },
|
101
|
-
date:->(d){ Date.parse(d.to_s) },
|
102
|
-
datetime:->(d){ DateTime.parse(d.to_s) },
|
103
|
-
decimal:->(d){ d.to_i },
|
104
|
-
float:->(d){ d.to_f },
|
105
|
-
integer:->(d){ d.to_i },
|
106
|
-
string:->(d){ d.to_s.gsub(/\t/,'') },
|
107
|
-
text:->(d){ d.to_s },
|
108
|
-
time:->(d){ DateTime.parse(d.to_s) },
|
109
|
-
timestamp:->(d){ DateTime.parse(d.to_s) },
|
110
|
-
}
|
111
|
-
|
112
|
-
# 適切な型に変換
|
113
|
-
def self.trans v
|
114
|
-
case v
|
115
|
-
when true; 1
|
116
|
-
when false; 0
|
117
|
-
else; v
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
# csv で fixtures を dump
|
122
|
-
def self.csv format
|
123
|
-
file_name = format[:file] || format[:table]
|
124
|
-
dir_name = format[:dir] || DUMP_DIR
|
125
|
-
outfile = "#{dir_name}#{file_name}.csv"
|
126
|
-
table_name = format[:table]
|
127
|
-
klass = PARENT.create_model(table_name)
|
128
|
-
attributes = klass.columns.map { |colum| colum.name }
|
129
|
-
CSV.open(outfile,'w') do |csv|
|
130
|
-
csv<< attributes
|
131
|
-
klass.all.each do |row|
|
132
|
-
csv<< attributes.map { |column| trans(row.send(column)) }
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
|
-
# yaml で fixtures を dump
|
138
|
-
def self.yml format
|
139
|
-
file_name = format[:file] || format[:table]
|
140
|
-
dir_name = format[:dir] || DUMP_DIR
|
141
|
-
outfile = "#{dir_name}#{file_name}.yml"
|
142
|
-
table_name = format[:table]
|
143
|
-
klass = PARENT::create_model(table_name)
|
144
|
-
attributes = klass.columns.map { |colum| colum.name }
|
145
|
-
|
146
|
-
columns = klass.columns
|
147
|
-
# テーブルからカラム情報を取り出し
|
148
|
-
column_hash = {}
|
149
|
-
columns.each { |col| column_hash[col.name] = col }
|
150
|
-
# 自動補完が必要なはずのカラム
|
151
|
-
lack_columns = columns.select { |c| !c.null and !c.default }.map{ |o| o.name.to_sym }
|
152
|
-
not_nullable_columns = columns.select { |c| !c.null }.map &:name
|
153
|
-
|
154
|
-
File.open(outfile,"w") do |f|
|
155
|
-
klass.all.each_with_index do |row,idx|
|
156
|
-
f<< "#{table_name}_#{idx}:\n" +
|
157
|
-
attributes.map { |col|
|
158
|
-
v = trans row.send(col)
|
159
|
-
v = "|-\n " + v.gsub(/\n/,%Q{\n }) if v.kind_of?(String) # Stringだと改行が入るので特殊処理
|
160
|
-
" #{col}: #{v}\n"
|
161
|
-
}.join
|
162
|
-
end
|
163
|
-
end
|
164
|
-
end
|
165
|
-
end
|
166
|
-
|
167
|
-
# Dumperと違ってデータの吐き出し処理をまとめたクラス
|
168
|
-
module Loader
|
169
|
-
PARENT = Flextures
|
170
|
-
|
171
|
-
# 型に応じて勝手にdefault値を設定する
|
172
|
-
COMPLETER = {
|
173
|
-
binary:->{ 0 },
|
174
|
-
boolean:->{ false },
|
175
|
-
date:->{ DateTime.now },
|
176
|
-
datetime:->{ DateTime.now },
|
177
|
-
decimal:->{ 0 },
|
178
|
-
float:->{ 0.0 },
|
179
|
-
integer:->{ 0 },
|
180
|
-
string:->{ "" },
|
181
|
-
text:->{ "" },
|
182
|
-
time:->{ DateTime.now },
|
183
|
-
timestamp:->{ DateTime.now },
|
184
|
-
}
|
185
|
-
|
186
|
-
# 型の変換を行う
|
187
|
-
TRANSLATER = {
|
188
|
-
binary:->(d){ d.to_i },
|
189
|
-
boolean:->(d){ (0==d || ""==d || !d) ? false : true },
|
190
|
-
date:->(d){ Date.parse(d.to_s) },
|
191
|
-
datetime:->(d){ DateTime.parse(d.to_s) },
|
192
|
-
decimal:->(d){ d.to_i },
|
193
|
-
float:->(d){ d.to_f },
|
194
|
-
integer:->(d){ d.to_i },
|
195
|
-
string:->(d){ d.to_s },
|
196
|
-
text:->(d){ d.to_s },
|
197
|
-
time:->(d){ DateTime.parse(d.to_s) },
|
198
|
-
timestamp:->(d){ DateTime.parse(d.to_s) },
|
199
|
-
}
|
200
|
-
|
201
|
-
# csv 優先で存在している fixtures をロード
|
202
|
-
def self.load format
|
203
|
-
file_name = format[:file] || format[:table]
|
204
|
-
dir_name = format[:dir] || LOAD_DIR
|
205
|
-
method = nil
|
206
|
-
method = :csv if File.exist? "#{dir_name}#{file_name}.csv"
|
207
|
-
method = :yml if File.exist? "#{dir_name}#{file_name}.yml"
|
208
|
-
self::send(method, format) if method
|
209
|
-
end
|
210
|
-
|
211
|
-
# fixturesをまとめてロード、主にテストtest/unit, rspec で使用する
|
212
|
-
#
|
213
|
-
# 全テーブルが対象
|
214
|
-
# fixtures :all
|
215
|
-
# テーブル名で一覧する
|
216
|
-
# fixtures :users, :items
|
217
|
-
# ハッシュで指定
|
218
|
-
# fixtures :users => :users2
|
219
|
-
def self.flextures *fixtures
|
220
|
-
# :allですべてのfixtureを反映
|
221
|
-
fixtures = ActiveRecord::Base.connection.tables if fixtures.size== 1 and :all == fixtures.first
|
222
|
-
fixtures_hash = fixtures.pop if fixtures.last and fixtures.last.is_a? Hash # ハッシュ取り出し
|
223
|
-
fixtures.each{ |table_name| Loader::load table: table_name }
|
224
|
-
fixtures_hash.each{ |k,v| Loader::load table: k, file: v } if fixtures_hash
|
225
|
-
fixtures
|
226
|
-
end
|
227
|
-
|
228
|
-
# CSVのデータをロードする
|
229
|
-
def self.csv format
|
230
|
-
table_name = format[:table].to_s
|
231
|
-
file_name = format[:file] || table_name
|
232
|
-
dir_name = format[:dir] || LOAD_DIR
|
233
|
-
inpfile = "#{dir_name}#{file_name}.csv"
|
234
|
-
klass = PARENT::create_model table_name
|
235
|
-
attributes = klass.columns.map &:name
|
236
|
-
filter = create_filter klass, Factory[table_name]
|
237
|
-
klass.delete_all
|
238
|
-
CSV.open( inpfile ) do |csv|
|
239
|
-
keys = csv.shift # keyの設定
|
240
|
-
warning "CSV", attributes, keys
|
241
|
-
csv.each do |values|
|
242
|
-
h = values.extend(Extensions::Array).to_hash(keys)
|
243
|
-
args = [h, file_name]
|
244
|
-
o = filter.call *args[0,filter.arity]
|
245
|
-
o.save
|
246
|
-
end
|
247
|
-
end
|
248
|
-
end
|
249
|
-
|
250
|
-
# YAML形式でデータをロードする
|
251
|
-
def self.yml format
|
252
|
-
table_name = format[:table].to_s
|
253
|
-
file_name = format[:file] || table_name
|
254
|
-
dir_name = format[:dir] || LOAD_DIR
|
255
|
-
inpfile = "#{dir_name}#{file_name}.yml"
|
256
|
-
klass = PARENT::create_model table_name
|
257
|
-
attributes = klass.columns.map &:name
|
258
|
-
filter = create_filter klass, Factory[table_name]
|
259
|
-
klass.delete_all
|
260
|
-
YAML.load(File.open(inpfile)).each do |k,h|
|
261
|
-
warning "YAML", attributes, h.keys
|
262
|
-
args = [h, file_name]
|
263
|
-
o = filter.call *args[0,filter.arity]
|
264
|
-
o.save
|
265
|
-
end
|
266
|
-
end
|
267
|
-
|
268
|
-
# 欠けたカラムを検知してメッセージを出しておく
|
269
|
-
def self.warning format, attributes, keys
|
270
|
-
(attributes-keys).each { |name| print "Warning: #{format} colum is missing! [#{name}]\n" }
|
271
|
-
(keys-attributes).each { |name| print "Warning: #{format} colum is left over! [#{name}]\n" }
|
272
|
-
end
|
273
|
-
|
274
|
-
# フィクスチャから取り出した値を、加工して欲しいデータにするフィルタを作成して返す
|
275
|
-
def self.create_filter klass, factory=nil
|
276
|
-
columns = klass.columns
|
277
|
-
# テーブルからカラム情報を取り出し
|
278
|
-
column_hash = {}
|
279
|
-
columns.each { |col| column_hash[col.name] = col }
|
280
|
-
# 自動補完が必要なはずのカラム
|
281
|
-
lack_columns = columns.select { |c| !c.null and !c.default }.map{ |o| o.name.to_sym }
|
282
|
-
not_nullable_columns = columns.select { |c| !c.null }.map &:name
|
283
|
-
# ハッシュを受け取って、必要な値に加工してからハッシュで返すラムダを返す
|
284
|
-
return->(h){
|
285
|
-
# テーブルに存在しないキーが定義されているときは削除
|
286
|
-
h.select! { |k,v| column_hash[k] }
|
287
|
-
o = klass.new
|
288
|
-
# 値がnilでないなら型をDBで適切なものに変更
|
289
|
-
h.each{ |k,v| nil==v || o[k] = TRANSLATER[column_hash[k].type].call(v) }
|
290
|
-
not_nullable_columns.each{ |k| o[k]==nil && o[k] = TRANSLATER[column_hash[k].type].call(k) }
|
291
|
-
# FactoryFilterを動作させる
|
292
|
-
factory.call(o) if factory
|
293
|
-
# 値がnilの列にデフォルト値を補間
|
294
|
-
lack_columns.each { |k| nil==o[k] && o[k] = COMPLETER[column_hash[k].type].call }
|
295
|
-
o
|
296
|
-
}
|
297
|
-
end
|
298
|
-
end
|
299
93
|
end
|
300
94
|
|
@@ -0,0 +1,129 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module Flextures
|
4
|
+
# データを吐き出す処理をまとめる
|
5
|
+
module Dumper
|
6
|
+
PARENT = Flextures
|
7
|
+
|
8
|
+
TRANSLATER = {
|
9
|
+
binary:->(d, format ){
|
10
|
+
d.to_s
|
11
|
+
},
|
12
|
+
boolean:->(d, format ){
|
13
|
+
(0==d || ""==d || !d) ? false : true
|
14
|
+
},
|
15
|
+
date:->(d, format ){
|
16
|
+
if format == :yml
|
17
|
+
return "null" if d.nil?
|
18
|
+
end
|
19
|
+
Time.parse(d.to_s).to_s
|
20
|
+
},
|
21
|
+
datetime:->(d, format ){
|
22
|
+
Time.parse(d.to_s).to_s
|
23
|
+
},
|
24
|
+
decimal:->(d, format ){
|
25
|
+
d.to_i
|
26
|
+
},
|
27
|
+
float:->(d, format){
|
28
|
+
d.to_f
|
29
|
+
},
|
30
|
+
integer:->(d, format){
|
31
|
+
d.to_i
|
32
|
+
},
|
33
|
+
string:->(s, format ){
|
34
|
+
if format == :yml
|
35
|
+
return "null" if s.nil?
|
36
|
+
s = s.to_s
|
37
|
+
s = s.gsub(/\t/," ") if s["\t"]
|
38
|
+
s = s.sub(/ +/, "") if s[0]==' '
|
39
|
+
s = "|-\n " + s.gsub(/\n/,"\n ") if s["\n"]
|
40
|
+
end
|
41
|
+
if format == :yml
|
42
|
+
return nil if s.nil? # nil は空白文字
|
43
|
+
s = s.to_s
|
44
|
+
end
|
45
|
+
s
|
46
|
+
},
|
47
|
+
text:->(s, format){
|
48
|
+
if format == :yml
|
49
|
+
return "null" if s.nil?
|
50
|
+
s = s.to_s
|
51
|
+
s = s.gsub(/\t/," ") if s["\t"]
|
52
|
+
s = s.sub(/ +/, "") if s[0]==' '
|
53
|
+
s = "|-\n " + s.gsub(/\n/,"\n ") if s["\n"]
|
54
|
+
end
|
55
|
+
if format == :csv
|
56
|
+
return nil if s.nil? # nil は空白文字
|
57
|
+
s = s.to_s
|
58
|
+
end
|
59
|
+
s
|
60
|
+
},
|
61
|
+
time:->(d, format ){
|
62
|
+
if format == :yml
|
63
|
+
return "null" if d.nil?
|
64
|
+
end
|
65
|
+
Time.parse(d.to_s).to_s
|
66
|
+
},
|
67
|
+
timestamp:->(d, format ){
|
68
|
+
if format == :yml
|
69
|
+
return "null" if d.nil?
|
70
|
+
end
|
71
|
+
Time.parse(d.to_s).to_s
|
72
|
+
},
|
73
|
+
}
|
74
|
+
|
75
|
+
# 適切な型に変換
|
76
|
+
def self.trans(v, type, format)
|
77
|
+
trans = TRANSLATER[type]
|
78
|
+
return trans.call( v, format ) if trans
|
79
|
+
v
|
80
|
+
end
|
81
|
+
|
82
|
+
# csv で fixtures を dump
|
83
|
+
def self.csv format
|
84
|
+
file_name = format[:file] || format[:table]
|
85
|
+
dir_name = format[:dir] || DUMP_DIR
|
86
|
+
outfile = "#{dir_name}#{file_name}.csv"
|
87
|
+
table_name = format[:table]
|
88
|
+
klass = PARENT.create_model(table_name)
|
89
|
+
attributes = klass.columns.map { |column| column.name }
|
90
|
+
CSV.open(outfile,'w') do |csv|
|
91
|
+
attr_type = klass.columns.map { |column| { name: column.name, type: column.type } }
|
92
|
+
csv<< attributes
|
93
|
+
klass.all.each do |row|
|
94
|
+
csv<< attr_type.map { |h| trans(row[h[:name]], h[:type], :csv) }
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# yaml で fixtures を dump
|
100
|
+
def self.yml format
|
101
|
+
file_name = format[:file] || format[:table]
|
102
|
+
dir_name = format[:dir] || DUMP_DIR
|
103
|
+
outfile = "#{dir_name}#{file_name}.yml"
|
104
|
+
table_name = format[:table]
|
105
|
+
klass = PARENT::create_model(table_name)
|
106
|
+
attributes = klass.columns.map { |colum| colum.name }
|
107
|
+
|
108
|
+
columns = klass.columns
|
109
|
+
# テーブルからカラム情報を取り出し
|
110
|
+
column_hash = {}
|
111
|
+
columns.each { |col| column_hash[col.name] = col }
|
112
|
+
# 自動補完が必要なはずのカラム
|
113
|
+
lack_columns = columns.select { |c| !c.null and !c.default }.map{ |o| o.name.to_sym }
|
114
|
+
not_nullable_columns = columns.select { |c| !c.null }.map &:name
|
115
|
+
|
116
|
+
File.open(outfile,"w") do |f|
|
117
|
+
klass.all.each_with_index do |row,idx|
|
118
|
+
f<< "#{table_name}_#{idx}:\n" +
|
119
|
+
klass.columns.map { |column|
|
120
|
+
colname, coltype = column.name, column.type
|
121
|
+
v = trans(row[colname], coltype, :yml)
|
122
|
+
" #{colname}: #{v}\n"
|
123
|
+
}.join
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
@@ -0,0 +1,143 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'ostruct'
|
4
|
+
require 'csv'
|
5
|
+
|
6
|
+
require 'flextures/flextures_base_config'
|
7
|
+
require 'flextures/flextures_extension_modules'
|
8
|
+
require 'flextures/flextures'
|
9
|
+
require 'flextures/flextures_factory'
|
10
|
+
|
11
|
+
module Flextures
|
12
|
+
# Dumperと違ってデータの吐き出し処理をまとめたクラス
|
13
|
+
module Loader
|
14
|
+
PARENT = Flextures
|
15
|
+
|
16
|
+
# 型に応じて勝手にdefault値を設定する
|
17
|
+
COMPLETER = {
|
18
|
+
binary:->{ 0 },
|
19
|
+
boolean:->{ false },
|
20
|
+
date:->{ DateTime.now },
|
21
|
+
datetime:->{ DateTime.now },
|
22
|
+
decimal:->{ 0 },
|
23
|
+
float:->{ 0.0 },
|
24
|
+
integer:->{ 0 },
|
25
|
+
string:->{ "" },
|
26
|
+
text:->{ "" },
|
27
|
+
time:->{ DateTime.now },
|
28
|
+
timestamp:->{ DateTime.now },
|
29
|
+
}
|
30
|
+
|
31
|
+
# 型の変換を行う
|
32
|
+
TRANSLATER = {
|
33
|
+
binary:->(d){ d.to_i },
|
34
|
+
boolean:->(d){ (0==d || ""==d || !d) ? false : true },
|
35
|
+
date:->(d){ Date.parse(d.to_s) },
|
36
|
+
datetime:->(d){ DateTime.parse(d.to_s) },
|
37
|
+
decimal:->(d){ d.to_i },
|
38
|
+
float:->(d){ d.to_f },
|
39
|
+
integer:->(d){ d.to_i },
|
40
|
+
string:->(d){ d.to_s },
|
41
|
+
text:->(d){ d.to_s },
|
42
|
+
time:->(d){ DateTime.parse(d.to_s) },
|
43
|
+
timestamp:->(d){ DateTime.parse(d.to_s) },
|
44
|
+
}
|
45
|
+
|
46
|
+
# csv 優先で存在している fixtures をロード
|
47
|
+
def self.load format
|
48
|
+
file_name = format[:file] || format[:table]
|
49
|
+
dir_name = format[:dir] || LOAD_DIR
|
50
|
+
method = nil
|
51
|
+
method = :csv if File.exist? "#{dir_name}#{file_name}.csv"
|
52
|
+
method = :yml if File.exist? "#{dir_name}#{file_name}.yml"
|
53
|
+
self::send(method, format) if method
|
54
|
+
end
|
55
|
+
|
56
|
+
# fixturesをまとめてロード、主にテストtest/unit, rspec で使用する
|
57
|
+
#
|
58
|
+
# 全テーブルが対象
|
59
|
+
# fixtures :all
|
60
|
+
# テーブル名で一覧する
|
61
|
+
# fixtures :users, :items
|
62
|
+
# ハッシュで指定
|
63
|
+
# fixtures :users => :users2
|
64
|
+
def self.flextures *fixtures
|
65
|
+
# :allですべてのfixtureを反映
|
66
|
+
fixtures = ActiveRecord::Base.connection.tables if fixtures.size== 1 and :all == fixtures.first
|
67
|
+
fixtures_hash = fixtures.pop if fixtures.last and fixtures.last.is_a? Hash # ハッシュ取り出し
|
68
|
+
fixtures.each{ |table_name| Loader::load table: table_name }
|
69
|
+
fixtures_hash.each{ |k,v| Loader::load table: k, file: v } if fixtures_hash
|
70
|
+
fixtures
|
71
|
+
end
|
72
|
+
|
73
|
+
# CSVのデータをロードする
|
74
|
+
def self.csv format
|
75
|
+
table_name = format[:table].to_s
|
76
|
+
file_name = format[:file] || table_name
|
77
|
+
dir_name = format[:dir] || LOAD_DIR
|
78
|
+
inpfile = "#{dir_name}#{file_name}.csv"
|
79
|
+
klass = PARENT::create_model table_name
|
80
|
+
attributes = klass.columns.map &:name
|
81
|
+
filter = create_filter klass, Factory[table_name], file_name, :csv
|
82
|
+
klass.delete_all
|
83
|
+
CSV.open( inpfile ) do |csv|
|
84
|
+
keys = csv.shift # keyの設定
|
85
|
+
warning "CSV", attributes, keys
|
86
|
+
csv.each do |values|
|
87
|
+
h = values.extend(Extensions::Array).to_hash(keys)
|
88
|
+
o = filter.call h
|
89
|
+
o.save
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# YAML形式でデータをロードする
|
95
|
+
def self.yml format
|
96
|
+
table_name = format[:table].to_s
|
97
|
+
file_name = format[:file] || table_name
|
98
|
+
dir_name = format[:dir] || LOAD_DIR
|
99
|
+
inpfile = "#{dir_name}#{file_name}.yml"
|
100
|
+
klass = PARENT::create_model table_name
|
101
|
+
attributes = klass.columns.map &:name
|
102
|
+
filter = create_filter klass, Factory[table_name], file_name, :yml
|
103
|
+
klass.delete_all
|
104
|
+
YAML.load(File.open(inpfile)).each do |k,h|
|
105
|
+
warning "YAML", attributes, h.keys
|
106
|
+
o = filter.call h
|
107
|
+
o.save
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# 欠けたカラムを検知してメッセージを出しておく
|
112
|
+
def self.warning format, attributes, keys
|
113
|
+
(attributes-keys).each { |name| print "Warning: #{format} colum is missing! [#{name}]\n" }
|
114
|
+
(keys-attributes).each { |name| print "Warning: #{format} colum is left over! [#{name}]\n" }
|
115
|
+
end
|
116
|
+
|
117
|
+
# フィクスチャから取り出した値を、加工して欲しいデータにするフィルタを作成して返す
|
118
|
+
def self.create_filter klass, factory, filename, ext
|
119
|
+
columns = klass.columns
|
120
|
+
# テーブルからカラム情報を取り出し
|
121
|
+
column_hash = {}
|
122
|
+
columns.each { |col| column_hash[col.name] = col }
|
123
|
+
# 自動補完が必要なはずのカラム
|
124
|
+
lack_columns = columns.select { |c| !c.null and !c.default }.map{ |o| o.name.to_sym }
|
125
|
+
not_nullable_columns = columns.select { |c| !c.null }.map &:name
|
126
|
+
# ハッシュを受け取って、必要な値に加工してからハッシュで返すラムダを返す
|
127
|
+
return->(h){
|
128
|
+
# テーブルに存在しないキーが定義されているときは削除
|
129
|
+
h.select! { |k,v| column_hash[k] }
|
130
|
+
o = klass.new
|
131
|
+
# 値がnilでないなら型をDBで適切なものに変更
|
132
|
+
h.each{ |k,v| nil==v || o[k] = TRANSLATER[column_hash[k].type].call(v) }
|
133
|
+
not_nullable_columns.each{ |k| o[k]==nil && o[k] = TRANSLATER[column_hash[k].type].call(k) }
|
134
|
+
# FactoryFilterを動作させる
|
135
|
+
factory.call(*[o, :load, filename, ext][0,factory.arity]) if factory
|
136
|
+
# 値がnilの列にデフォルト値を補間
|
137
|
+
lack_columns.each { |k| nil==o[k] && o[k] = COMPLETER[column_hash[k].type].call }
|
138
|
+
o
|
139
|
+
}
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flextures
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.9.
|
4
|
+
version: 1.9.7
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,41 +9,40 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-04-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
16
|
-
requirement:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
|
-
- -
|
19
|
+
- - '='
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: 1.
|
21
|
+
version: 1.1.3
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements:
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - '='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 1.1.3
|
25
30
|
- !ruby/object:Gem::Dependency
|
26
31
|
name: jeweler
|
27
|
-
requirement:
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
28
33
|
none: false
|
29
34
|
requirements:
|
30
|
-
- -
|
35
|
+
- - '='
|
31
36
|
- !ruby/object:Gem::Version
|
32
|
-
version: 1.
|
37
|
+
version: 1.8.3
|
33
38
|
type: :development
|
34
39
|
prerelease: false
|
35
|
-
version_requirements:
|
36
|
-
- !ruby/object:Gem::Dependency
|
37
|
-
name: rcov
|
38
|
-
requirement: &70149925735040 !ruby/object:Gem::Requirement
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
39
41
|
none: false
|
40
42
|
requirements:
|
41
|
-
- -
|
43
|
+
- - '='
|
42
44
|
- !ruby/object:Gem::Version
|
43
|
-
version:
|
44
|
-
type: :development
|
45
|
-
prerelease: false
|
46
|
-
version_requirements: *70149925735040
|
45
|
+
version: 1.8.3
|
47
46
|
description: load and dump fixtures
|
48
47
|
email: babanba.n@gmail.com
|
49
48
|
executables: []
|
@@ -68,8 +67,10 @@ files:
|
|
68
67
|
- lib/flextures/flextures.rake
|
69
68
|
- lib/flextures/flextures.rb
|
70
69
|
- lib/flextures/flextures_base_config.rb
|
70
|
+
- lib/flextures/flextures_dumper.rb
|
71
71
|
- lib/flextures/flextures_extension_modules.rb
|
72
72
|
- lib/flextures/flextures_factory.rb
|
73
|
+
- lib/flextures/flextures_loader.rb
|
73
74
|
- lib/flextures/flextures_railtie.rb
|
74
75
|
- lib/flextures/rspec_flextures_support.rb
|
75
76
|
- lib/flextures/testunit_flextures_support.rb
|
@@ -88,7 +89,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
88
89
|
version: '0'
|
89
90
|
segments:
|
90
91
|
- 0
|
91
|
-
hash: -
|
92
|
+
hash: -377856707
|
92
93
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
93
94
|
none: false
|
94
95
|
requirements:
|
@@ -97,7 +98,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
97
98
|
version: '0'
|
98
99
|
requirements: []
|
99
100
|
rubyforge_project:
|
100
|
-
rubygems_version: 1.8.
|
101
|
+
rubygems_version: 1.8.21
|
101
102
|
signing_key:
|
102
103
|
specification_version: 3
|
103
104
|
summary: load and dump fixtures
|