1

I get an xml file which I have to parse. From it I take data for 2 models. Product and Attachment. An attachment is an image for product. This is how the code goes, I will follow it by an explanation:

def add_to_db_from_file
    transaction do
        save!
        xml = Nokogiri::XML(File.open(self.file.current_path))
        xml.xpath("//item").each do |item|
            product_hash = %w[campaign_name widget_name title description short_message price category
                                                    subcategory url product_id aff_code].each_with_object({}) do |n, h|
                                                        h[n.intern] = n != 'price' ? item.at(n).text : item.at(n).text.to_i
                                            end
            attachments_array = item.css('image_urls').map do |url| 
                                                        url.text.split(' ')
                                                    end.flatten
            @product = self.products.create!(product_hash)
            attachments_array.each do |p|
                @product.attachments.create!(remote_picture_url: p)
            end
        end
    end
end

I open an xml file and I parse it creating a hash with the proucts params(product_hash). At the same time a product can have one or more Attachments given by the tag image_urls . I parse after that tag for each product and make an array with the urls of the images a product has. I create the product and for each image I create an attachment.

However I want to create the attachments with the help of nested attributes so I added this in my product model:

accepts_nested_attributes_for :attachments

And this in my permited params in product controller(along the other attributes):

params.require(:product).permit( attachments_attributes: [:id, :product_id, :picture, :remote_picture_url])

I have tried making a hash out of attachments_array and merging it with the product_hash thus it should create the attachments along with the product using the nested attributes:

attachments_array = item.css('image_urls').map do |url| 
                     {remote_picture_url: url.text.split(' ') }
                   end.flatten
@product = self.products.create!(product_hash.merge!({attachments_attributes: attachments_array}))

However this clearly is not a solution as I get:

NoMethodError: undefined method `gsub' for #<Array:0x007f3b6d832138>

My question is how can I send an array of nested attributes along with the main object to be created?

1 Answer 1

1

You can build product attachments then save the product

product = Product.new(product_hash)
attachements_array.each do |url|
  product.attachements.build(remote_picture_url: url)
end
product.save

If you want to include all your items in a hash, then your product hash will be

product_hash = {product_attr1: product_attr1_val, product_attr2: product_attr2_val, attachementes_attributes: [{attach_attr1: attach_attr1_val}, {attach_attr1: attach_attr1_val}] }
Product.create(product_hash)

More on that: http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html

Sign up to request clarification or add additional context in comments.

1 Comment

So I wasn't wrong, and I managed to figure out once you stated that my attachments_array had an array as an attribute in the hash. I will let this question here since it could be useful . Even more so when you gave a clear answer to what you should send.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.