0

I am building a rails 6 app and I am stuck on an issue.

Let's say I have a table tasks which has 3 fields:

  • id
  • state
  • description

The description field is in fact a rich_text field thanks to ActionText.

My problem is that I have a csv file composed of 3 columns (id, state, description) and, during initialization of the app, I want to populate my database with it, using bulk import.

Normally, if description was a normal column, I would do something like this:

Task.insert_all(
 # My csv converted in array of hashes [{state: YY, description: ZZZZZZZ}]
)

But as description is not really an attribute of the table tasks, it won't work. How can I still use bulk import to import large set of data, but still use action_text fields?

Right now, I am forced to use "one by one" insertions which takes a very long time!

Thank you for any leads you can bring.

Thomas
  • 183
  • 1
  • 14
  • Can u show an example of the "one by one" insertions you're doing so I can get a clearer understanding of what you're trying to accomplish? – Joel Blum Apr 06 '20 at 12:16
  • I mean I iterate through the csv table and for each row, I do `Task.create(state: YY, description: ZZZZZZZ')`. But in that case, I have n insertion which takes a very long time for a large CSV. – Thomas Apr 08 '20 at 14:08

1 Answers1

2

I think the easiest way to do this is by splitting your input like this:

# Tasks
tasks = { id: XX, state: YY, ... }

# Descriptions
descriptions = { record_type: 'Task', record_id: XX, name: 'description', body: 'Actual body' }

Then you can do something like this:

Task.insert_all(tasks)
ActionText::RichText.insert_all(descriptions)

Is this what your are looking for?

========================================================

Update:

Just to clarify how this works, we need to understand that RichText model works as any other model in Rails, but serializing the information as showed here: https://github.com/rails/rails/blob/master/actiontext/app/models/action_text/rich_text.rb#L11

To see what is really being extracted from the database we can use the helper *field*_before_type_cast. For example:

descriptions = [ { record_type: 'Task', record_id: XX, name: 'description', body: '<p>EXAMPLE</p>' } ]
ActionText::RichText.insert_all(descriptions)

ActionText::RichText.last.body => <ActionText::Content....>
ActionText::RichText.last.body_before_type_cast => '<p>EXAMPLE</p>'

Also, keep in mind that you can have one rich text per record (is a 1 - N polymorphic association). So, if you try to insert a second description for your Task it won't work

Jorge Vargas
  • 640
  • 6
  • 13
  • I have the impression that it won't work. When I look an instance created with `Task.create(state: YY, description: ZZZ')`, `Task.last.description.body` will show ``. You can see that ActionText formated my description before saving it. If you try to save like you said `ActionText::RichText.create( record_type: 'Task', record_id: XX, name: 'Description', body: 'Actual body' )`, the record is saved. But when I query `Task.last.description`, It returned ` – Thomas Apr 08 '20 at 14:15
  • Weird, are you sure the record is saved? because the `ActionText::RichText` object that was returned at the end of your example doesn't have id and all records saved to database have id. – Jorge Vargas Apr 09 '20 at 18:47
  • Also, note that before return the record ActionText will serialize the body (https://github.com/rails/rails/blob/master/actiontext/app/models/action_text/rich_text.rb). But that is not what is saved in DB. – Jorge Vargas Apr 09 '20 at 18:48
  • My bad! I made a mistake during testing. You are right: everything works. Thank you for your detailed explanations – Thomas Apr 16 '20 at 17:09
  • Yay! glad to help! <3 – Jorge Vargas Apr 17 '20 at 17:26