How can I load some ActiveRecord models from a YAM

2019-02-02 02:23发布

问题:

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?

回答1:

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)


回答2:

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


回答3:

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.



回答4:

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.