views:

47

answers:

1

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

+2  A: 

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")
jigfox
@Jens Fahnenbruck, thanks, but I assume there is no model 'Question', just the table and the yml file.
Freewind
I have this limitation, because there are some tables have no corresponding Models, such as 'questions_tags'
Freewind
I've updated my anser
jigfox
@Jens, thank you, but sorry, I still need your help. Actually, there is not only the table 'questions', there are some other tables like 'tags/questions_tags/answers/users' and so on, I can't explicitly define model for them. Is there any other common way? For example, only given a connection, table_name, and a hash(record), and insert it to database?
Freewind
than create dummy models for all these tables. It should work
jigfox
Yes the model name should be the singular and capital version of the table name. I've updated my answer now it should work
jigfox
with `create dummy models` I meant to create a correctly named dummy for each table
jigfox
@Jens, sorry. Your updated answer works good at most of time, but if there is a join table(no 'id' column), it may fail. For example, my database is postgresql, now I have an exception: PGError: ERROR: column "id" does not existLINE 1: ...01.421875', 26, '2010-05-28 15:58:01.421875') RETURNING "id"
Freewind
I want to know, can we just work with 'connection', not depend on the ActiveRecord::Base?
Freewind
Yes you can. See my latest update
jigfox
But we should build the sql manually... Isn't there a method like:connection.insert('questions', {:title=>'xx', :content=>'xx'})?
Freewind
not that I know of. If you want to go through the connection directly you have to build your queries on your own. But why won't you create a Model for each Table, even if it's a very basic model? You can also create models without an id field.
jigfox
It seems the best solution, I'm tring now. @Jens, thank you so much!
Freewind
you're welcome!
jigfox