I'm trying to save some lookup table data out to a YAML file so that later when I need to set up my app on a different machine I can load the data in as seed data.
The data is stuff like select options, and it's pretty much set, so no worries about the live data changing between serializing and deserializing.
I have output the data like this...
file = File.open("#{RAILS_ROOT}/lib/tasks/questions/questions.yml", 'w')
questions = Question.find(:all, :order => 'order_position')
file << YAML::dump(questions)
file.close()
And I can load the file like this...
questions = YAML.load_file('lib/tasks/questions/questions.yml')
However, when I try to save a question I get this error...
>> questions[0].save
NoMethodError: undefined method `save' for #<YAML::Object:0x2226b84>
What is the correct way to do this?
I tried your scenario and I did not have any issues. I did the following changes to your YAML file creation logic:
yml_file = Rails.root.join('lib', 'tasks', 'questions', 'questions.yml')
File.open(yml_file, 'w') do |file|
questions = Question.order(:order_position).to_a
YAML::dump(questions, file)
end
I was able to retrieve the questions
list as follows:
yml_file = Rails.root.join('lib', 'tasks', 'questions', 'questions.yml')
question_attributes_list = YAML.load_file(yml_file).map(&:attributes)
questions = Question.create(question_attributes_list)
Create a seed.yml
file in db
directory. Add a YAML document for each model you want to create. This document should contain a list of hash. Each hash should contain model attributes.
users:
- login: jake
password: jake123
password_confirmation: jake123
first_name: Jake
last_name: Driver
- login: Jane
password: jane123
password_confirmation: jane123
first_name: Jane
last_name: McCain
categories:
products:
In your seed.rb file
seed_file = File.join(Rails.root, 'db', 'seed.yml')
config = YAML::load_file(seed_file)
User.create(config["users"])
Category.create(config["categories"])
Product.create(config["products"])
Run the rake task to load the rows
rake db:seed
Does the accepted answer actually answer the question? It looks like the asker wanted to save the models, not just retrieve them from a YAML file.
To actually save the loaded model(s) back to the database you need to fool ActiveRecord
into thinking the model needs saving. You can do it with this rather dirty bit of code
questions = YAML.load_file("#{RAILS_ROOT}/lib/tasks/questions/questions.yml")
questions.each{|q| q.instance_variable_set("@new_record", true); q.save}
It works and saved my bacon once or twice.
If you're using Rails 2.3.4 (or above), they have a seeds.rb
file that can be found in your applications db
folder. This lets you define basic active record creates, and when you've set up your new project, you can simply call:
rake db:seed
There is an excellent Railscast on it here, and a good blog post about it here. If you're not using Rails 2.3.4 (Or, ideally, 2.3.5), I highly recommend updating for these cool features, and addition security/bug fixes.