All notable changes to this project will be documented in this file.
- Handle Invisible Chars in headers. #107 by @tracyloisel
- Ruby 2.7 compatibility. #93 by @perezperret
- Improve algorithm to detect separators. #88 by @brain-geek
to:
accepts anything that responds to#call
(lambda, procs, classes etc). #72 by @pcreux inspired by #71 by @macfanatic.
valid_header?
returnsfalse
when the CSV is malformed instead of raising an exception. #85 by @mltsy- Header infos (ex:
extra_columns
) aren't discarded after running an import. #83 by @mltsy
- We now pass the
column
object as the third parameter of thecolumn
block for advanced usage. #73 by @stas.
column :extra, as: [/extra/], to: ->(value, user, column) do
attribute = column.name.sub(/^extra /, '')
user[attribute] = value
end
- after_save supports block with arity of 2 for access to raw attributes. #68 by @macfanatic.
class Importer
model Task
column :assignee, to: ->(name) { User.active.find_by(name: name) }
after_save do |task, attributes|
if task.errors[:assignee].present? && attributes['Assignee'].present?
task.errors.add(:assignee, "'#{ attributes['Assignee'] }' is not part of this project."
end
end
end
- support Proc identifiers. #69 by @danielweinmann
class Importer
identifier ->(user) { user.email.present? ? :email : [:company_id, :employee_id] }
end
- Rows are now aware of their line number. #63 by @paulodeleo
import.report.invalid_rows.map { |row| [row.line_number, row.model.email, row.errors] }
# => [ [2, "INVALID_EMAIL", { "email" => "is invalid" } ] ]
after_build
block is only called once (#47 by @fxgallego and #52 @pnomolos)after_build
andafter_save
blocks don't leak between runtime definitions (#47 by @fxgallego and #52 @pnomolos)
- You can customize the encoding with the
encoding
option. Default isUTF-8
. (#38 by @egg-chicken)
- Empty cells are now empty strings. You don't have to check for a nil value when applying a transformation anymore.
# Prior to 0.3, an empty cell turns into `nil`
column :email, to: ->(email) { email.downcase unless email.nil? }
# From 0.3, an empty cell turns into `""`
column :email, to: ->(email) { email.downcase }
- You can now skip an import in the
after_build
callback:
UserImport.new(file: csv_file) do
# Skip existing records
after_build do |user|
skip! if user.persisted?
end
end
after_save
callback.
progress_bar = ProgressBar.new
UserImport.new(file: my_file) do
after_save do |user|
progress_bar.increment
end
end
- You can define a composite identifier made of multiple columns.
# Update records with matching company_id AND employee_id
identifier :company_id, :employee_id
- You can set a custom
quote_char
at runtime. (#26 by @shvetsovdm)
UserImport.new(file: csv_file, quote_char: "'")
- You can now change the configuration at runtime. Example:
UserImport.new(file: csv_file) do
after_build do |user|
user.import_by_user = current_user
end
end
-
Add
after_build
hooks to perform arbitrary operations on a model before saving it. -
identifier
does not have to be a required attribute anymore. That enables you to useid
as an identifier and import new entries without having to provide anid
run!
was not returning a report object when the header was invalid.
- When calling
run!
on an import with invalid header we update the report object instead of raising an exception.
- Initial Release