activerecord-bixformer 0.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.
@@ -0,0 +1,11 @@
1
+ module ActiveRecord
2
+ module Bixformer
3
+ module Modeler
4
+ class Csv < ::ActiveRecord::Bixformer::Modeler::Base
5
+ def initialize
6
+ super(:csv)
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,47 @@
1
+ require 'active_record'
2
+
3
+ module ActiveRecord
4
+ module Bixformer
5
+ module Runner
6
+ class Base
7
+ attr_reader :errors
8
+
9
+ def initialize(format)
10
+ @format = format
11
+ @modelers = []
12
+ @errors = []
13
+ end
14
+
15
+ def add_modeler(*modelers)
16
+ modelers.each do |modeler|
17
+ unless modeler.format.to_s == @format.to_s
18
+ raise ArgumentError.new "modeler format unmatches to #{@format} as runner format : #{modeler.format}"
19
+ end
20
+
21
+ @modelers.push modeler
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def available_modelers
28
+ if @modelers.empty?
29
+ raise ArgumentError.new "Not exist any available modelers. You have to regist modeler by add_modeler."
30
+ end
31
+
32
+ @modelers
33
+ end
34
+
35
+ def active_modeler(force_detect = nil)
36
+ return @active_modeler if ! force_detect && @active_modeler
37
+
38
+ @active_modeler = detect_modeler
39
+ end
40
+
41
+ def detect_modeler
42
+ available_modelers.first
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,123 @@
1
+ require 'csv'
2
+
3
+ module ActiveRecord
4
+ module Bixformer
5
+ module Runner
6
+ class Csv < ::ActiveRecord::Bixformer::Runner::Base
7
+ def initialize
8
+ super(:csv)
9
+ end
10
+
11
+ def import(csv_data, options = {})
12
+ modeler = active_modeler(true)
13
+ model_constant = modeler.model_name.to_s.camelize.constantize
14
+
15
+ @errors = []
16
+ options[:headers] = true
17
+
18
+ model_attributes_list = parse_csv_rows(::CSV.parse(csv_data, options))
19
+
20
+ model_constant.transaction do
21
+ model_attributes_list.each.with_index(1) do |model_attributes, index|
22
+ next unless model_attributes&.present?
23
+
24
+ identified_value = model_attributes[model_constant.primary_key]
25
+
26
+ activerecord = if identified_value
27
+ find_activerecord(model_constant, identified_value)
28
+ else
29
+ build_activerecord(model_constant, model_attributes)
30
+ end
31
+
32
+ unless save_activerecord(activerecord, model_attributes)
33
+ @errors += make_error_messages(activerecord, index)
34
+ end
35
+ end
36
+
37
+ raise ::ActiveRecord::Rollback unless @errors.empty?
38
+ end
39
+
40
+ @errors.empty? ? true : false
41
+ end
42
+
43
+ def export(active_records_or_relation, options = {})
44
+ modeler = active_modeler(true)
45
+ generator = modeler.new_module_instance(:generator, :csv_row, modeler, active_records_or_relation.first)
46
+ csv_titles = make_csv_titles(generator)
47
+
48
+ ::CSV.generate(options) do |csv|
49
+ csv << csv_titles
50
+
51
+ active_records_or_relation.each do |activerecord|
52
+ generator = modeler.new_module_instance(:generator, :csv_row, modeler, activerecord)
53
+
54
+ csv << make_csv_row(generator, csv_titles)
55
+ end
56
+ end
57
+ end
58
+
59
+ private
60
+
61
+ def make_csv_titles(generator)
62
+ generator.compile.available_csv_titles
63
+ end
64
+
65
+ def make_csv_row(generator, csv_titles)
66
+ model_attributes = generator.generate
67
+
68
+ csv_titles.map { |title| model_attributes[title] }
69
+ end
70
+
71
+ def parse_csv_rows(csv_rows)
72
+ modeler = active_modeler
73
+
74
+ csv_rows.map do |csv_row|
75
+ generator = modeler.new_module_instance(:generator, :active_record, modeler, csv_row)
76
+
77
+ parse_csv_row(generator)
78
+ end
79
+ end
80
+
81
+ def parse_csv_row(generator)
82
+ generator.generate
83
+ end
84
+
85
+ def find_activerecord(model_class, id)
86
+ model_class.find(id)
87
+ end
88
+
89
+ def build_activerecord(model_class, attributes)
90
+ model_class.new(attributes)
91
+ end
92
+
93
+ def save_activerecord(activerecord, assigned_attributes)
94
+ # CSVで削除が可能だが、削除フラグは _destroy というattributesに入っており、こんなcolumnは存在しないので、このままだとエラーになる
95
+ # そのため、ここで要素から削除しておく
96
+ is_destroy = assigned_attributes.delete(:_destroy)
97
+
98
+ if activerecord.persisted?
99
+ if is_destroy
100
+ activerecord.destroy
101
+ else
102
+ activerecord.update(assigned_attributes)
103
+ end
104
+ else
105
+ activerecord.save
106
+ end
107
+ end
108
+
109
+ def make_error_messages(activerecord, csv_row_index)
110
+ activerecord.errors.full_messages.map do |msg|
111
+ I18n.t(
112
+ :"bixformer.csv.errors.format", {
113
+ default: "Entry(%{csv_row_index}): %{message}",
114
+ csv_row_index: csv_row_index,
115
+ message: msg
116
+ }
117
+ )
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,50 @@
1
+ module ActiveRecord
2
+ module Bixformer
3
+ module Translator
4
+ class I18n
5
+ attr_accessor :config, :model, :attribute_arguments_map, :model_arguments
6
+
7
+ def initialize
8
+ @attribute_arguments_map = {}
9
+ @model_arguments = {}
10
+ end
11
+
12
+ def translate_attribute(attribute_name)
13
+ translate('attributes', ".#{attribute_name}", @attribute_arguments_map[attribute_name])
14
+ end
15
+
16
+ def translate_model
17
+ translate('models', '', @model_arguments)
18
+ end
19
+
20
+ private
21
+
22
+ def translate(type_key, extra_key, arguments)
23
+ root_scope = normalize_scope_value(@config[:scope] || 'activerecord')
24
+ extend_scopes = @config[:extend_scopes] || []
25
+ arguments = arguments || {}
26
+ model_key = [*@model.parents, @model].map(&:name).join('/')
27
+
28
+ key_candidates = [*extend_scopes.map { |s| ".#{normalize_scope_value(s)}" }, ''].map do |extend_scope|
29
+ "#{root_scope}#{extend_scope}.#{type_key}.#{model_key}#{extra_key}"
30
+ end
31
+
32
+ found_key = key_candidates.find { |key| ::I18n.exists?(key) }
33
+
34
+ raise ::I18n::MissingTranslationData.new(::I18n.locale, key_candidates.last, arguments) unless found_key
35
+
36
+ ::I18n.t(found_key, arguments || {})
37
+ end
38
+
39
+ def normalize_scope_value(scope_value)
40
+ return nil if scope_value.blank?
41
+
42
+ scope_value = scope_value.map(&:to_s).join(".") if scope_value.is_a?(::Array)
43
+
44
+ # delimiter が付いていたら削除
45
+ scope_value.to_s.sub(/\A\./, '').sub(/\.\z/, '')
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,5 @@
1
+ module ActiveRecord
2
+ module Bixformer
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
@@ -0,0 +1,8 @@
1
+ require 'activerecord-bixformer/version'
2
+ Dir["#{File.dirname(__FILE__)}/activerecord-bixformer/**/base.rb"].each { |f| require f }
3
+ Dir["#{File.dirname(__FILE__)}/activerecord-bixformer/**/*.rb"].each { |f| require f }
4
+
5
+ module ActiveRecord
6
+ module Bixformer
7
+ end
8
+ end
metadata ADDED
@@ -0,0 +1,267 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: activerecord-bixformer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Hiroaki Otsu
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-09-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activerecord
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 2.3.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 2.3.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: sqlite3
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.3'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: i18n
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 0.7.0
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 0.7.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: enumerize
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 2.0.0
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 2.0.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: booletania
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 0.0.2
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 0.0.2
83
+ - !ruby/object:Gem::Dependency
84
+ name: bundler
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.12'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1.12'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rake
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '10.0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '10.0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rspec
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '3.0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '3.0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: database_rewinder
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: 0.6.4
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: 0.6.4
139
+ - !ruby/object:Gem::Dependency
140
+ name: stackprof
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: 0.2.9
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: 0.2.9
153
+ - !ruby/object:Gem::Dependency
154
+ name: pry
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: pry-doc
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
181
+ - !ruby/object:Gem::Dependency
182
+ name: pry-byebug
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - ">="
186
+ - !ruby/object:Gem::Version
187
+ version: '0'
188
+ type: :development
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - ">="
193
+ - !ruby/object:Gem::Version
194
+ version: '0'
195
+ - !ruby/object:Gem::Dependency
196
+ name: pry-stack_explorer
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - ">="
200
+ - !ruby/object:Gem::Version
201
+ version: '0'
202
+ type: :development
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - ">="
207
+ - !ruby/object:Gem::Version
208
+ version: '0'
209
+ description: a framework for xross transformer between ActiveRecord and other format.
210
+ email:
211
+ - ootsuhiroaki@gmail.com
212
+ executables: []
213
+ extensions: []
214
+ extra_rdoc_files: []
215
+ files:
216
+ - ".gitignore"
217
+ - ".rspec"
218
+ - ".travis.yml"
219
+ - Gemfile
220
+ - README-ja.md
221
+ - README.md
222
+ - Rakefile
223
+ - activerecord-bixformer.gemspec
224
+ - lib/activerecord-bixformer.rb
225
+ - lib/activerecord-bixformer/attribute/base.rb
226
+ - lib/activerecord-bixformer/attribute/boolean.rb
227
+ - lib/activerecord-bixformer/attribute/booletania.rb
228
+ - lib/activerecord-bixformer/attribute/date.rb
229
+ - lib/activerecord-bixformer/attribute/enumerize.rb
230
+ - lib/activerecord-bixformer/attribute/override.rb
231
+ - lib/activerecord-bixformer/attribute/time.rb
232
+ - lib/activerecord-bixformer/generator/active_record.rb
233
+ - lib/activerecord-bixformer/generator/base.rb
234
+ - lib/activerecord-bixformer/generator/csv_row.rb
235
+ - lib/activerecord-bixformer/model/base.rb
236
+ - lib/activerecord-bixformer/model/csv/base.rb
237
+ - lib/activerecord-bixformer/model/csv/indexed.rb
238
+ - lib/activerecord-bixformer/modeler/base.rb
239
+ - lib/activerecord-bixformer/modeler/csv.rb
240
+ - lib/activerecord-bixformer/runner/base.rb
241
+ - lib/activerecord-bixformer/runner/csv.rb
242
+ - lib/activerecord-bixformer/translator/i18n.rb
243
+ - lib/activerecord-bixformer/version.rb
244
+ homepage: https://github.com/aki2o/activerecord-bixformer
245
+ licenses: []
246
+ metadata: {}
247
+ post_install_message:
248
+ rdoc_options: []
249
+ require_paths:
250
+ - lib
251
+ required_ruby_version: !ruby/object:Gem::Requirement
252
+ requirements:
253
+ - - ">="
254
+ - !ruby/object:Gem::Version
255
+ version: '0'
256
+ required_rubygems_version: !ruby/object:Gem::Requirement
257
+ requirements:
258
+ - - ">="
259
+ - !ruby/object:Gem::Version
260
+ version: '0'
261
+ requirements: []
262
+ rubyforge_project:
263
+ rubygems_version: 2.5.1
264
+ signing_key:
265
+ specification_version: 4
266
+ summary: a framework for xross transformer between ActiveRecord and other format.
267
+ test_files: []