Commit 6a22ebe6 by liyijie

Add importable feature

parent d92af47e
......@@ -2,23 +2,37 @@ PATH
remote: .
specs:
tallty_import_export (0.1.0)
activesupport (~> 6.0.3)
caxlsx
roo
roo-xls
tallty_form
zip-zip
GEM
remote: https://gems.ruby-china.com/
specs:
activemodel (6.0.3.4)
activesupport (= 6.0.3.4)
activesupport (6.0.3.4)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
tzinfo (~> 1.1)
zeitwerk (~> 2.2, >= 2.2.2)
caxlsx (3.0.2)
htmlentities (~> 4.3, >= 4.3.4)
mimemagic (~> 0.3)
nokogiri (~> 1.10, >= 1.10.4)
rubyzip (>= 1.3.0, < 3)
concurrent-ruby (1.1.7)
diff-lcs (1.4.4)
htmlentities (4.3.4)
i18n (1.8.5)
concurrent-ruby (~> 1.0)
mimemagic (0.3.5)
mini_portile2 (2.4.0)
minitest (5.14.2)
nokogiri (1.10.10)
mini_portile2 (~> 2.4.0)
rake (12.3.3)
......@@ -46,6 +60,15 @@ GEM
rubyzip (2.3.0)
spreadsheet (1.2.6)
ruby-ole (>= 1.0)
tallty_duck_record (1.0.2)
activemodel (~> 6.0.3)
activesupport (~> 6.0.3)
tallty_form (1.0.0)
tallty_duck_record
thread_safe (0.3.6)
tzinfo (1.2.8)
thread_safe (~> 0.1)
zeitwerk (2.4.1)
zip-zip (0.3)
rubyzip (>= 1.0.0)
......
require "active_support/core_ext/hash"
require "tallty_import_export/version"
require 'axlsx'
require 'tallty_form'
module TalltyImportExport
class Error < StandardError; end
extend ActiveSupport::Autoload
autoload :Common
autoload :Exportable
autoload :Importable
autoload :Common, 'tallty_import_export/common'
autoload :Exportable, 'tallty_import_export/exportable'
autoload :Importable, 'tallty_import_export/importable'
class Error < StandardError; end
end
......@@ -13,6 +13,7 @@ module TalltyImportExport
name: column.comment || column.name,
attr_type: column.type,
format: column.type == :string ? :string : nil,
primary_key: column.name == 'id' ? true : false
}
end
end
......
......@@ -9,15 +9,19 @@ module TalltyImportExport
# name: 属性的中文名
# attr_type: 属性的类型
# format: excel是否需要特定的格式,目前主要是类似于身份证号,可以用string
# method: 本地调用的方法
# chain: 对象属性通过链式调用
# method: 导出时本地调用的方法
# chain: 导出时对象属性通过链式调用
included do
end
module ClassMethods
def export_records records
def export_records records, options={}
exportable_defaults
options = options.with_indifferent_access
header_keys = options.delete(:keys)
Axlsx::Package.new do |pack|
workbook = pack.workbook
# excel导出样式
......@@ -58,10 +62,14 @@ module TalltyImportExport
@row_height ||= options.delete(:row_height) || 35
@width ||= options.delete(:width) || 30
@filename ||= options.delete(:filename)
@headers = self.try(:export_headers) || self.try(:headers) || self.try(:model_headers)
@headers = export_headers
@headers.map! {|header| header.with_indifferent_access}
end
def export_headers
self.try(:headers) || self.try(:model_headers)
end
# 处理一个记录的数据
def handle_data record, header
data =
......
module TalltyImportExport
module Importable
extend ActiveSupport::Concern
include Common
# key: 属性的英文名
# name: 属性的中文名
# attr_type: 属性的类型
# format: excel是否需要特定的格式,目前主要是类似于身份证号,可以用string
# convert: 导入时候,把excel的内容转换成导入时候代码逻辑需要的内容
# primary_key: 是否是主键
included do
end
module ClassMethods
def import_xlsx xlsx_file, associations, options={}
# 先处理获取出来Excel每行的数据, line_info
options = options.with_indifferent_access
@headers = options.delete(:headers) || import_headers
@primary_keys = options.delete(:primary_keys) || @headers.map { |header| header[:primary_key] ? header[:key].to_sym : nil }.compact
excel_hash = @headers.reduce({}) do |h, header|
h[header[:key]] = header[:name]
h
end
file_path = xlsx_file.is_a?(String) ? xlsx_file : xlsx_file.path
xlsx = Roo::Excelx.new(file_path)
xlsx.each_with_pagename do |_sheetname, sheet|
sheet.each(**excel_hash).with_index do |line_info, index|
next if index == 0
# 转换处理导入的数据格式
line_info = convert_data line_info, @headers
# 处理每行对于导入的动作,处理line_info
import_record line_info, associations, primary_keys: @primary_keys
end
end
end
def convert_data line_info, headers
line_info.with_indifferent_access.reduce({}) do |h, (k, v)|
header = headers.find do |_header|
_header[:key].to_sym == k.to_sym
end
h[k.to_sym] = header[:convert] ?
self.send(header[:convert], v) : v
h
end.with_indifferent_access
end
def import_headers
self.try(:headers) || self.try(:model_headers)
end
### 这个方法是可以由复杂业务进行重载的 ###
def import_record line_info, associations, primary_keys: []
record = if primary_keys.present?
_record = associations.find_or_initialize_by(line_info.clone.extract!(*primary_keys))
_record.attributes = line_info.clone.except!(*primary_keys)
_record
else
associations.new(line_info)
end
record.save!
end
end
end
end
......@@ -12,11 +12,7 @@ Gem::Specification.new do |spec|
spec.license = "MIT"
spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
spec.metadata["allowed_push_host"] = "https://git.tallty.com/open-source/tallty_import_export"
spec.metadata["homepage_uri"] = spec.homepage
spec.metadata["source_code_uri"] = "https://git.tallty.com/open-source/tallty_import_export"
spec.metadata["changelog_uri"] = "https://git.tallty.com/open-source/tallty_import_export"
spec.platform = Gem::Platform::RUBY
# Specify which files should be added to the gem when it is released.
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
......@@ -31,4 +27,6 @@ Gem::Specification.new do |spec|
spec.add_dependency('caxlsx')
spec.add_dependency('roo')
spec.add_dependency('roo-xls')
spec.add_dependency('tallty_form')
spec.add_dependency('activesupport')
end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment