Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to load the data from a .yml file to database?

There is a table questions, and a data file questions.yml. Assume there is no 'Question' model.

'questions.yml' has some recodes dump from the table.

---
questions_001:
  title: ttt1
  content: ccc1
questions_002:
  title: ttt2
  content: ccc2

I want to load the data from the yml file, insert them to database. But I can't use rake db:fixtures:load, because it will treat the content as 'erb' template, which is not want I want

So I want to write another rake task, to load the data manually.

I can read the records by:

File.open("#{RAILS_ROOT}/db/fixtures/#{table_name}.yml", 'r') do |file|
   YAML::load(file).each do |record|
      # how to insert the record??
   end
end

But I don't know how to insert them.


Edit:

I have tried:

Class.new(ActiveRecord::Base).create(record)

and

class Dummy < ActiveRecord::Base {}
Dummy.create(rcord)

But nothing inserted to database

like image 507
Freewind Avatar asked Feb 27 '23 19:02

Freewind


2 Answers

Try this after loading the date from the yml file to records:

class Question < ActiveRecord::Base
  # Question model just to import the yml file
end
records.each { |record| Question.create(record) }

You can simply create a model just for importing. You don't need to create the app/models/question.rb. Just write the code above in the script responsible for the importing.

UPDATE:

You can use the following function:

def create_class(class_name, superclass, &block)
  klass = Class.new superclass, &block
  Object.const_set class_name, klass
end

source

File.open("#{RAILS_ROOT}/db/fixtures/#{table_name}.yml", 'r') do |file|
  YAML::load(file).each do |record|
    model_name = table_name.singularize.camelize
    create_class(model_name, ActiveRecod::Base) do
      set_table_name table_name.to_sym
    end
    Kernel.const_get(model_name).create(record)
  end
end

To use the connection directly you can use the following:

ActiveRecord::Base.connection.execute("YOUR SQL CODE")
like image 90
jigfox Avatar answered Mar 03 '23 03:03

jigfox


Got it working thanks to @jigfox 's answer. Had to modify a bit for the full implementation now with Rails 4.

table_names = Dir.glob(Rails.root + 'app/models/**.rb').map { |s| Pathname.new(s).basename.to_s.gsub(/\.rb$/,'') }    

table_names.each do |table_name|
  table_name = table_name.pluralize
  path = "#{Rails.root}/db/fixtures/#{table_name}.yml"
  if File.exists?(path)
    File.open(path, 'r') do |file|
      y = YAML::load(file)
      if !y.nil? and y
        y.each do |record|
          model_name = table_name.singularize.camelize
          rec = record[1] 
          rec.tap { |hs| hs.delete("id") }
          Kernel.const_get(model_name).create(rec)
        end
      end
    end
  end
end
like image 34
zagros Avatar answered Mar 03 '23 05:03

zagros