heart_seed 0.0.1.beta1 → 0.0.1.beta2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 00e700cd31219d035de3f79465a7100761273f02
4
- data.tar.gz: ae3bb179f7bd42d1f0529dd495bdc8b96fbbca7a
3
+ metadata.gz: b6cdf153eeacd0a2bb25e04f0b086d6c3d5b47f5
4
+ data.tar.gz: d7c2518396273ff9de9771c6985b6f3590fedd97
5
5
  SHA512:
6
- metadata.gz: 43c0dbba243860dfc16ace5d25f6ea84ed4518bda85bd82365fdf16081f48297c4ecb411897e8414616368e323575ac33c626c6dbc886f6db2e980a943b966af
7
- data.tar.gz: 8e1d46e47673368a8840d19aff78de1fd1410a251825c33bec1b64b0fb9ab1a24e3c8ab9d735c977e39539ccd56bbeb73e18a10cd20fef2745652c67d16fe877
6
+ metadata.gz: 6634e532e3fbef27ceb93dce2d138428df7ed6992fab00f5164b8b8a4918888fa396a7d2998da703533bc2f9613a4ac31f0496c9ae07dfd5322e9c2c666a8e90
7
+ data.tar.gz: d99648ac07a0816d9c11c9c7e5c9dfda693010b63b6d2a224a7ea90655a63cff751ceeaa65290bf19966712cbce72a7ab5f7f9ada57c7944e3e160bccff96e48
data/README.md CHANGED
@@ -1,12 +1,15 @@
1
1
  # [WIP] HeartSeed
2
2
 
3
- seed util (excel -> yaml -> db)
3
+ seed util (excel -> yaml -> db)
4
4
 
5
+ [![Gem Version](https://badge.fury.io/rb/heart_seed.svg)](http://badge.fury.io/rb/heart_seed)
5
6
  [![Build Status](https://travis-ci.org/sue445/heart_seed.svg)](https://travis-ci.org/sue445/heart_seed)
6
7
  [![Code Climate](https://codeclimate.com/github/sue445/heart_seed.png)](https://codeclimate.com/github/sue445/heart_seed)
7
8
  [![Coverage Status](https://img.shields.io/coveralls/sue445/heart_seed.svg)](https://coveralls.io/r/sue445/heart_seed?branch=master)
8
9
  [![Dependency Status](https://gemnasium.com/sue445/heart_seed.svg)](https://gemnasium.com/sue445/heart_seed)
9
10
 
11
+ [![Stories in Ready](https://badge.waffle.io/sue445/heart_seed.png?label=ready&title=Ready)](https://waffle.io/sue445/heart_seed)
12
+
10
13
  ## Installation
11
14
 
12
15
  Add this line to your application's Gemfile:
@@ -27,13 +30,105 @@ Or install it yourself as:
27
30
  * create `config/heart_seed.yml`, `db/xls`, `db/seeds`
28
31
  * append to `db/seeds.rb`
29
32
  2. Create xls
33
+ * sheet name (xls,xlsx) = table name (DB)
30
34
  * example https://github.com/sue445/heart_seed/tree/master/spec/dummy/db/xls
31
35
  3. `bundle exec rake heart_seed:xls`
32
36
  * Generate yml to `db/seeds`
33
- * If you want to specify files: `FILES=comments_and_likes.xls SHEETS=comments,likes bundle exec rake heart_seed:xls`
34
- 4. `bundle exec rake db:seed`
37
+ * If you want to specify files: `FILES=comments_and_likes.xls SHEETS=comments,likes bundle exec rake heart_seed:xls`
38
+ 4. `bundle exec rake db:seed` or `bundle exec rake heart_seed:db:seed`
35
39
  * Import yml to db
36
- * If you want to specify tables: `TABLES=articles,comments bundle exec rake db:seed`
40
+ * Exists `TABLES`, `CATALOGS` options
41
+
42
+ examples
43
+
44
+ ```sh
45
+ TABLES=articles,comments bundle exec rake db:seed
46
+ CATALOGS=article,user bundle exec rake db:seed
47
+ ```
48
+
49
+ ### other Rails
50
+
51
+ append this to `Rakefile`
52
+
53
+ ```ruby
54
+ require 'heart_seed/tasks'
55
+ ```
56
+
57
+ ### Snippets
58
+ #### config/heart_seed.yml
59
+ ```yml
60
+ seed_dir: db/seeds
61
+ xls_dir: db/xls
62
+ catalogs:
63
+ # user:
64
+ # - users
65
+ # - user_profiles
66
+ ```
67
+
68
+ #### db/seeds.rb
69
+ ```ruby
70
+ # Appended by `rake heart_seed:init`
71
+ HeartSeed::DbSeed.import_all
72
+ ```
73
+
74
+ ## Specification
75
+ ### Supported xls/xlsx format
76
+
77
+ Example sheet
78
+
79
+ id | title | description | created_at | | this is dummy
80
+ --- | ------ | ------------ | -------------- | --- | --------------
81
+ 1 | title1 | description1 | 2014/6/1 12:10 | | foo
82
+ 2 | title2 | description2 | 2014/6/2 12:10 | | baz
83
+
84
+ * Sheet name is mapped table name
85
+ * If sheet name is not found in database, this is ignored
86
+ * 1st row : table column names
87
+ * If the spaces are included in the middle, right columns are ignored
88
+ * 2nd row ~ : records
89
+ * [ActiveSupport::TimeWithZone](http://api.rubyonrails.org/classes/ActiveSupport/TimeWithZone.html) is used for timezone
90
+
91
+ ### Yaml format
92
+
93
+ example
94
+
95
+ ```yaml
96
+ ---
97
+ articles_1:
98
+ id: 1
99
+ title: title1
100
+ description: description1
101
+ created_at: '2014-06-01 12:10:00 +0900'
102
+ articles_2:
103
+ id: 2
104
+ title: title2
105
+ description: description2
106
+ created_at: '2014-06-02 12:10:00 +0900'
107
+ ```
108
+
109
+ * same as [ActiveRecord::FixtureSet](http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html) format
110
+
111
+ ### Catalog
112
+ Catalog is table groups defined in heart_seed.yml
113
+
114
+ example
115
+
116
+ ```yml
117
+ catalogs:
118
+ user:
119
+ - users
120
+ - user_profiles
121
+ ```
122
+
123
+ `user` catalog = `users`, `user_profiles` tables
124
+
125
+
126
+ You can specify the catalogs at `db:seed` task
127
+
128
+ ```sh
129
+ CATALOGS=user bundle exec rake db:seed
130
+ # same to) TABLES=users,user_profiles bundle exec rake db:seed
131
+ ```
37
132
 
38
133
  ## Contributing
39
134
 
@@ -87,7 +87,7 @@ module HeartSeed
87
87
  #
88
88
  # @return [ Hash{ String => Hash{ String => Object } } ]
89
89
  def self.read_sheet(sheet, row_prefix)
90
- header_keys = sheet.row(HEADER_ROW)
90
+ header_keys = select_left_of_blank(sheet.row(HEADER_ROW))
91
91
  fixtures = {}
92
92
 
93
93
  (HEADER_ROW + 1 .. sheet.last_row).each do |row_num|
@@ -95,11 +95,11 @@ module HeartSeed
95
95
  header_keys.each_with_index do |key, col_index|
96
96
  value = sheet.cell(row_num, col_index + 1)
97
97
 
98
- case sheet.celltype(row_num, col_index + 1)
99
- when :float
98
+ case value
99
+ when Float
100
100
  # ex) 1.0 -> 1
101
101
  value = value.to_i if value == value.to_i
102
- when :date, :time, :datetime
102
+ when DateTime
103
103
  # value is DateTime and localtime, but not included TimeZone(UTC)
104
104
  time = Time.zone.at(value.to_i - Time.zone.utc_offset)
105
105
  value = time.to_s
@@ -116,5 +116,15 @@ module HeartSeed
116
116
 
117
117
  fixtures
118
118
  end
119
+
120
+ def self.select_left_of_blank(array)
121
+ response = []
122
+ array.each do |element|
123
+ break unless element
124
+ break if element.respond_to?(:blank?) && element.blank?
125
+ response << element
126
+ end
127
+ response
128
+ end
119
129
  end
120
130
  end
@@ -21,30 +21,49 @@ module HeartSeed
21
21
  #
22
22
  # @param seed_dir [String]
23
23
  # @param tables [Array<String>,String] table names array or comma separated table names. if empty, import all seed yaml. if not empty, import only these tables.
24
- def self.import_all(seed_dir: HeartSeed::Helper.seed_dir, tables: [])
25
- target_tables = parse_arg_tables(tables)
24
+ def self.import_all(seed_dir: HeartSeed::Helper.seed_dir, tables: ENV["TABLES"], catalogs: ENV["CATALOGS"])
25
+ # use tables in catalogs
26
+ target_tables = parse_arg_catalogs(catalogs)
27
+ if target_tables.empty?
28
+ # use tables
29
+ target_tables = parse_string_or_array_arg(tables)
30
+ end
26
31
 
32
+ ActiveRecord::Migration.verbose = true
27
33
  Dir.glob(File.join(seed_dir, "*.yml")) do |file|
28
34
  table_name = File.basename(file, '.*')
29
35
  next unless target_table?(table_name, target_tables)
30
36
 
31
- begin
32
- model_class = table_name.classify.constantize
33
- bulk_insert(source_file: file, model_class: model_class)
34
- puts "[INFO] #{file} -> #{table_name}"
35
- rescue => e
36
- puts "[ERROR] #{e.message}"
37
+ ActiveRecord::Migration.say_with_time("#{file} -> #{table_name}") do
38
+ begin
39
+ model_class = table_name.classify.constantize
40
+ bulk_insert(source_file: file, model_class: model_class)
41
+ ActiveRecord::Migration.say("[INFO] success", true)
42
+ rescue => e
43
+ ActiveRecord::Migration.say("[ERROR] #{e.message}", true)
44
+ end
37
45
  end
38
46
  end
39
47
  end
40
48
 
41
- def self.parse_arg_tables(tables)
49
+ def self.parse_string_or_array_arg(tables)
42
50
  return [] unless tables
43
51
  return tables if tables.class == Array
44
52
 
45
53
  tables.class == String ? tables.split(",") : []
46
54
  end
47
55
 
56
+ def self.parse_arg_catalogs(catalogs)
57
+ array_catalogs = parse_string_or_array_arg(catalogs)
58
+ return [] if array_catalogs.empty?
59
+
60
+ tables = []
61
+ array_catalogs.each do |catalog|
62
+ tables += HeartSeed::Helper.catalog_tables(catalog)
63
+ end
64
+ tables.compact
65
+ end
66
+
48
67
  private
49
68
  def self.target_table?(source_table, target_tables)
50
69
  return true if target_tables.empty?
@@ -11,6 +11,7 @@ module HeartSeed
11
11
  {
12
12
  "seed_dir" => "db/seeds",
13
13
  "xls_dir" => "db/xls",
14
+ "catalogs" => {},
14
15
  }
15
16
  end
16
17
  end
@@ -45,5 +46,16 @@ module HeartSeed
45
46
  def self.root_dir=(dir)
46
47
  @root_dir = Pathname.new(dir)
47
48
  end
49
+
50
+ # @return [Hash{String => Array<String>}] key: catalog name, value: table names
51
+ def self.catalogs
52
+ config["catalogs"] || {}
53
+ end
54
+
55
+ # @param catalog_name [String]
56
+ # @return [Array<String>] table names in a specify catalog
57
+ def self.catalog_tables(catalog_name)
58
+ self.catalogs[catalog_name] || []
59
+ end
48
60
  end
49
61
  end
@@ -1,7 +1,7 @@
1
1
  module HeartSeed
2
2
  class Railtie < ::Rails::Railtie
3
3
  rake_tasks do
4
- load "heart_seed/tasks/heart_seed.rake"
4
+ require "heart_seed/tasks"
5
5
  end
6
6
  end
7
7
  end
@@ -0,0 +1 @@
1
+ load "heart_seed/tasks/heart_seed.rake"
@@ -1,10 +1,10 @@
1
1
  namespace :heart_seed do
2
2
  desc "create dir and file"
3
- task :init => ["config/heart_seed.yml", "db/xls", "db/seeds"] do
3
+ task :init => ["config/heart_seed.yml", "db/xls/.gitkeep", "db/seeds/.gitkeep"] do
4
4
  template = <<RUBY
5
5
 
6
6
  # Appended by `rake heart_seed:init`
7
- HeartSeed::DbSeed.import_all(tables: ENV["TABLES"])
7
+ HeartSeed::DbSeed.import_all
8
8
 
9
9
  RUBY
10
10
 
@@ -15,43 +15,64 @@ RUBY
15
15
  template = <<YAML
16
16
  seed_dir: db/seeds
17
17
  xls_dir: db/xls
18
+ catalogs:
19
+ # user:
20
+ # - users
21
+ # - user_profiles
18
22
  YAML
19
23
 
20
24
  create_file("config/heart_seed.yml", template)
21
25
  end
22
26
 
27
+ file "db/xls/.gitkeep" => "db/xls" do
28
+ create_file("db/xls/.gitkeep")
29
+ end
30
+
31
+ file "db/seeds/.gitkeep" => "db/seeds" do
32
+ create_file("db/seeds/.gitkeep")
33
+ end
34
+
23
35
  directory "config"
24
36
  directory "db/xls"
25
37
  directory "db/seeds"
26
38
 
27
- desc "create seed files by xls directory"
39
+ desc "create seed files by xls directory (options: FILES=table1.xls,table2.xlsx SHEETS=sheet1,sheet2)"
28
40
  task :xls => :environment do
41
+ ActiveRecord::Migration.verbose = true
29
42
  Dir.glob(File.join(HeartSeed::Helper.xls_dir, "*.{xls,xlsx}")) do |file|
30
43
  next if File.basename(file) =~ /^~/
31
44
 
32
45
  next unless target_file?(file)
33
46
 
34
- puts "Source File: #{file}"
35
- sheets = HeartSeed::Converter.table_sheets(file)
36
- sheets.each do |sheet|
37
- unless ActiveRecord::Base.connection.table_exists?(sheet)
38
- puts " [#{sheet}] Table is not found"
39
- next
40
- end
41
-
42
- next unless target_sheet?(sheet)
43
-
44
- dist_file = File.join(HeartSeed::Helper.seed_dir, "#{sheet}.yml")
45
- fixtures = HeartSeed::Converter.convert_to_yml(source_file: file, source_sheet: sheet, dist_file: dist_file)
46
- if fixtures
47
- puts " [#{sheet}] Create seed: #{dist_file}"
48
- else
49
- puts " [#{sheet}] Sheet is empty"
47
+ ActiveRecord::Migration.say_with_time("Source File: #{file}") do
48
+ sheets = HeartSeed::Converter.table_sheets(file)
49
+ sheets.each do |sheet|
50
+ unless ActiveRecord::Base.connection.table_exists?(sheet)
51
+ ActiveRecord::Migration.say("[#{sheet}] Table is not found", true)
52
+ next
53
+ end
54
+
55
+ next unless target_sheet?(sheet)
56
+
57
+ dist_file = File.join(HeartSeed::Helper.seed_dir, "#{sheet}.yml")
58
+ fixtures = HeartSeed::Converter.convert_to_yml(source_file: file, source_sheet: sheet, dist_file: dist_file)
59
+ if fixtures
60
+ ActiveRecord::Migration.say("[#{sheet}] Create seed: #{dist_file}", true)
61
+ else
62
+ ActiveRecord::Migration.say(" [#{sheet}] Sheet is empty", true)
63
+ end
50
64
  end
51
65
  end
52
66
  end
53
67
  end
54
68
 
69
+ namespace :db do
70
+ desc "Load the seed data from db/seeds/*.yml (options: TABLES=table1,table2 CATALOGS=catalog1,catalog2)"
71
+ task :seed => :environment do
72
+ HeartSeed::DbSeed.import_all
73
+ end
74
+ end
75
+
55
76
  private
56
77
  def target_file?(file)
57
78
  return true if ENV["FILES"].blank?
@@ -65,9 +86,9 @@ YAML
65
86
  ENV["SHEETS"].split(",").include?(sheet)
66
87
  end
67
88
 
68
- def create_file(file, str)
89
+ def create_file(file, str = nil)
69
90
  open(file, "w") do |out|
70
- out.write(str)
91
+ out.write(str) if str
71
92
  end
72
93
 
73
94
  puts "create: #{file}"
@@ -1,3 +1,3 @@
1
1
  module HeartSeed
2
- VERSION = "0.0.1.beta1"
2
+ VERSION = "0.0.1.beta2"
3
3
  end
Binary file
@@ -56,4 +56,20 @@ YAML
56
56
 
57
57
  it{ should == ["articles", "Sheet2"] }
58
58
  end
59
+
60
+ describe "#select_left_of_blank" do
61
+ subject{ HeartSeed::Converter.select_left_of_blank(array) }
62
+
63
+ context "When not include blank cell" do
64
+ let(:array){ ["id", "name"] }
65
+
66
+ it{ should eq ["id", "name"] }
67
+ end
68
+
69
+ context "When include blank cell" do
70
+ let(:array){ ["id", "name", "", "this is not table column"] }
71
+
72
+ it{ should eq ["id", "name"] }
73
+ end
74
+ end
59
75
  end
@@ -9,9 +9,16 @@ describe HeartSeed::DbSeed do
9
9
  end
10
10
 
11
11
  describe "#import_all" do
12
- subject{ HeartSeed::DbSeed.import_all(seed_dir: seed_dir, tables: tables) }
12
+ subject{ HeartSeed::DbSeed.import_all(seed_dir: seed_dir, tables: tables, catalogs: catalogs) }
13
13
 
14
14
  let(:seed_dir){ FIXTURE_DIR }
15
+ let(:tables) { [] }
16
+ let(:catalogs){ [] }
17
+
18
+ before do
19
+ # FIXME can not clear if using `DatabaseRewinder.clean`
20
+ DatabaseRewinder.clean_all
21
+ end
15
22
 
16
23
  after do
17
24
  # FIXME can not clear if using `DatabaseRewinder.clean`
@@ -19,8 +26,6 @@ describe HeartSeed::DbSeed do
19
26
  end
20
27
 
21
28
  context "When empty tables" do
22
- let(:tables) { [] }
23
-
24
29
  it{ expect{ subject }.to change(Article, :count).by(2) }
25
30
  it{ expect{ subject }.to change(Comment, :count).by(2) }
26
31
  it{ expect{ subject }.to change(Like , :count).by(1) }
@@ -33,10 +38,24 @@ describe HeartSeed::DbSeed do
33
38
  it{ expect{ subject }.to change(Comment, :count).by(0) }
34
39
  it{ expect{ subject }.to change(Like , :count).by(0) }
35
40
  end
41
+
42
+ context "When specify catalogs" do
43
+ let(:catalogs){ ["article"] }
44
+
45
+ before do
46
+ allow(HeartSeed::Helper).to receive(:catalogs){
47
+ { "article" => ["articles", "likes"] }
48
+ }
49
+ end
50
+
51
+ it{ expect{ subject }.to change(Article, :count).by(2) }
52
+ it{ expect{ subject }.to change(Comment, :count).by(0) }
53
+ it{ expect{ subject }.to change(Like , :count).by(1) }
54
+ end
36
55
  end
37
56
 
38
- describe "#parse_arg_tables" do
39
- subject{ HeartSeed::DbSeed.parse_arg_tables(tables) }
57
+ describe "#parse_string_or_array_arg" do
58
+ subject{ HeartSeed::DbSeed.parse_string_or_array_arg(tables) }
40
59
 
41
60
  where(:tables, :expected) do
42
61
  [
@@ -51,4 +70,32 @@ describe HeartSeed::DbSeed do
51
70
  it{ should eq expected }
52
71
  end
53
72
  end
73
+
74
+ describe "#parse_arg_catalogs" do
75
+ subject{ HeartSeed::DbSeed.parse_arg_catalogs(catalogs) }
76
+
77
+ before do
78
+ allow(HeartSeed::Helper).to receive(:catalogs){
79
+ {
80
+ "article" => ["articles", "likes"],
81
+ "user" => ["users", "user_profiles"],
82
+ }
83
+ }
84
+ end
85
+
86
+ where(:catalogs, :expected) do
87
+ [
88
+ [nil , []],
89
+ ["" , []],
90
+ ["article" , %w(articles likes)],
91
+ ["article,user" , %w(articles likes users user_profiles)],
92
+ [%w(article) , %w(articles likes)],
93
+ [%w(article user) , %w(articles likes users user_profiles)],
94
+ ]
95
+ end
96
+
97
+ with_them do
98
+ it{ should eq expected }
99
+ end
100
+ end
54
101
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: heart_seed
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1.beta1
4
+ version: 0.0.1.beta2
5
5
  platform: ruby
6
6
  authors:
7
7
  - sue445
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-06-16 00:00:00.000000000 Z
11
+ date: 2014-06-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -298,6 +298,7 @@ files:
298
298
  - lib/heart_seed/db_seed.rb
299
299
  - lib/heart_seed/helper.rb
300
300
  - lib/heart_seed/railtie.rb
301
+ - lib/heart_seed/tasks.rb
301
302
  - lib/heart_seed/tasks/heart_seed.rake
302
303
  - lib/heart_seed/version.rb
303
304
  - spec/data/articles.xls