Reputation: 1710
I used nokogiri to parse a xml document into array of hashes:
helpers/countries.helper
module CountriesHelper
def parse
@countries = ['australia', 'canada', 'france']
@countries.inject([]) do |memo, country|
File.open("public/#{country}.xml") do |f|
xml = Nokogiri::XML(f)
path = "//country/stores/"
memo << xml.xpath(path).map do |x|
{ 'country' => x.parent['country'],
'store' => x['store']}
end
end
end
# [{"country"=>"australia", "store"=>"store1"}, {"country"=>"france", "store"=>"store2"}]
How can I save this array of hashes format into my database? Lets say I have two models Country and Store.
Upvotes: 5
Views: 8610
Reputation: 34336
You can store your array of hashes in a text
field in your database.
Something like this in your migration file:
create_table "your_table", force: true do |t|
t.text "your_column_name"
end
Or, if you already have the table in the database and just want to add the new column to the table:
class Migration0001
def change
add_column :your_table, :your_column_name, :text
end
end
Just so you know, if you want to save a Hash
object in your database and if you define the column type as :text
, then Rails should be able to serialize it properly, and you won't need to use serialize
explicitly in your model.
But, in your case, it's an Array
of Hash
, so it's an Array
object that needs to be saved in the database, so you need to serialize the field in your model:
serialize :your_column_name, Array
That way, you can save an Array
of Hashes
in the database. Hope this helps.
Upvotes: 4
Reputation: 32955
You can serialize
an attribute, which means saving it as a particular type of object.
#in your model
serialize :store_hashes, Array
The field should be a text
field in the database. I don't know whether or not that's a good idea in this particular instance - i suspect it isn't. But that's how you save an array of hashes to the database.
http://apidock.com/rails/ActiveRecord/Base/serialize/class
Upvotes: 3
Reputation: 12592
Assuming country has many stores. Storing the hash in database would make very little sense (in my opinion). Storing in individual tables would make much more sense and easy for querying.
module CountriesHelper
def parse
@countries = ['australia', 'canada', 'france']
@countries.inject([]) do |memo, country|
File.open("public/#{country}.xml") do |f|
xml = Nokogiri::XML(f)
path = "//country/stores/"
memo << xml.xpath(path).map do |x|
{ 'country' => x.parent['country'],
'store' => x['store']}
country = Country.find_by_name(x.parent['country'])
if country.nil?
country = Country.create(name: x.parent['country'])
end
country.stores.create(name: x['store'])
end
end
end
Database transactions are meant to be invoked from Model; you can refactor later.
class Country < ActiveRecord::Base
has_many :stores
end
class Store < ActiveRecord::Base
belongs_to :country
end
Upvotes: 0