Skip to content

Instantly share code, notes, and snippets.

@TsubasaKawajiri
Last active June 25, 2020 11:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save TsubasaKawajiri/c239964797266f496c63892c4c335ebe to your computer and use it in GitHub Desktop.
Save TsubasaKawajiri/c239964797266f496c63892c4c335ebe to your computer and use it in GitHub Desktop.
csvから読んだり呼んだりdbに書いたりする
class BaseCsvLoader
class_attribute :file_path
class << self
def file_path(path)
self.file_path = path
end
def load
CSV.read(file_path, headers: false, row_sep: "\n")
end
end
class BaseItem
class_attribute :attributes, default: {}
class << self
def attribute(attr, options = {})
key = options.fetch(:key, attr)
attributes[key] = attr
end
def inherited(subclass)
subclass.attributes = {}
end
end
def initialize(item)
@item = item
klass = self.class
attributes.each do |key, _attr|
next if klass.method_defined?(key)
const_name = key.upcase
klass.define_method(key) { @item[klass.const_get(const_name)] } if klass.const_defined?(const_name)
end
end
def to_hash
attributes.each_with_object({}) do |(key, _attr), hash|
raise(NotImplementedError, "You must implement #{self.class}##{key}") unless respond_to?(key)
hash[key] = public_send(key)
end
end
alias to_h to_hash
def create?
raise(NotImplementedError, "You must implement #{self.class}##{__method__}")
end
def update?
raise(NotImplementedError, "You must implement #{self.class}##{__method__}")
end
def destroy?
raise(NotImplementedError, "You must implement #{self.class}##{__method__}")
end
end
class BaseRecordOperator
class_attribute :model
class_attribute :find_key
class << self
def model(model)
self.model = model
end
def find_key(find_key)
self.find_key = find_key
end
end
def initialize(item:)
@item = item
@item_hash = item.to_h
end
def operate
if @item.create?
create
elsif @item.update?
update
elsif @item.destroy?
destroy
end
end
private
def create
record = model.new(@item_hash)
record.save
end
def update
record = model.find_by(find_key => @item_hash[find_key])
record.assign_attributes(@item_hash)
record.save
end
def destroy
record = model.find_by(find_key => @item_hash[find_key])
record.destroy if record.present?
end
end
class Example
def modify_books
BookCsvLoader.new.load.each do |row|
item = Book.new(row)
BookDBOperator.new(item).operate
end
end
end
class BookCsvLoader < BaseCsvLoader
file_path 'hoge.csv'
end
module Constants
ID = 1
TITLE = 2
AUTHOR = 3
end
class Book < BaseItem
include Constants
attribute :id
attribute :title
attribute :author
def author
@item[AUTHOR] || 'unknown'
end
def create?
!update?
end
def update?
Book.exists?(id: id)
end
def destroy?
false
end
end
class BookRecordOperator < BaseRecordOperator
model Book
find_key :id
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment