Writing out a rake task to import from csv, one would tend to write
Article.create(
category_id: row[0],
label: row[1],
name: row[2],
integer: row[3],
priority: row[4]
)
But these need to be refactored taking into account a meta-structure where
Class Import
has_many :importattributes
The following is syntactically incorrect
Article.create(
import.importattributes.each do |importattribute|
m_attr = importattribute.mapped_attribute
sequence = importattribute.position.to_i
m_attr: row[sequence]
end
)
on the line complaining about syntax error, unexpected ':', expecting 'end'
m_attr: row[sequence]
If that line is commented out, other actions run as they do not parse this error beforehand.
I assume this is mistaken for the proper creation of array of attributes, because an update action, on a per attribute basis
import.importattributes.each do |importattribute|
m_attr = importattribute.mapped_attribute
sequence = importattribute.position.to_i
Article.update(m_attr: row[sequence])
end
does not raise the error.
CodePudding user response:
This is not a valid syntax m_attr: row[sequence]
. When used as an argument for update
it is treated as a hash { m_attr: row[sequence] }
and curly brackets can be omitted.
Article.create(
import.importattributes.each do |importattribute| # returns `import.importattributes`
# and used as argument for `create`
# nothing from `each` block is used
m_attr = importattribute.mapped_attribute # `m_attr` is unused
sequence = importattribute.position.to_i
m_attr: row[sequence] # invalid syntax
# at the very least it has to be wrapped in {} and used with hashrocket syntax
# to make use of m_attr variable.
# { m_attr => row[sequence] }
end
)
create
accepts a hash of attributes to create a single record or an array of hashes to create multiple records. The return value of the import logic has to be one of these two options. For clarity, it can be done in three steps:
attributes = {}
import.importattributes.each do |importattribute|
attribute_name = importattribute.mapped_attribute
csv_column = importattribute.position.to_i
attributes[attribute_name] = row[csv_column] }
end
Article.create(attributes)
or in one step using inject
Article.create(
import.importattributes.inject({}) do |attributes, importattribute|
attributes[importattribute.mapped_attribute] = row[importattribute.position.to_i]
attributes
end
)