How to seed data with ActionText has_rich_text?

2.4k views Asked by At

In my model, I have:

class Listing < ApplicationRecord
  ...
  has_rich_text :description
  ...
 end

In my seeds.rb:

@listing = Listing.new(
      title: 'CODE VEIN',
      price: 59.99 * 100,
      description:  "<p>#{Faker::Lorem.paragraphs(number: 30).join(' ')}</p>",
      seller_id: seller.id,
      release_date: Date.parse('Sep 26, 2019'),
      status: :active,
      esrb: 'MATURE'
    )

Listing.description comes up nil, causing my NOT NULL constraint to error.

I've debugged with pry, and tried @listing.description.body= text or @listing.description.body = ActionText::Content.new(text), both still cause the listing#description to be nil.

This is an API Only project, but I use Trix RTE in the front-end react app. Is there a specific method to seed rich_text columns?

3

There are 3 answers

4
max On BEST ANSWER

ActionText stores the actual contents in a seperate action_text_rich_texts table which uses a polymorphic assocation to link back to the model that its attached to.

# This migration comes from action_text (originally 20180528164100)
class CreateActionTextTables < ActiveRecord::Migration[6.0]
  def change
    create_table :action_text_rich_texts do |t|
      t.string     :name, null: false
      t.text       :body, size: :long
      t.references :record, null: false, polymorphic: true, index: false

      t.timestamps

      t.index [ :record_type, :record_id, :name ], name: "index_action_text_rich_texts_uniqueness", unique: true
    end
  end
end

The JavaScript component of ActionText (which is really the whole point) automatically sends AJAX requests when the user user interacts with Trix to create/update the row in the action_text_rich_texts table even before you have saved the record you're creating.

When you then submit the form you're actually submitting the id to the row on the action_text_rich_texts table and not the contents. Then when you save your model it updates the corresponding row on action_text_rich_texts with the record_type and record_id from the model. Its a pretty awkward solution that is built around the idea of never having to add columns to your model.

I don't really see the point in using ActionText in an API as the whole point is to add a quick and dirty Trix implementation to classical rails apps. You really should be able to solve this with just a single text column instead. Especially as that will let you access the contents without joining.

1
Marcelo Ribeiro On

There must be something else going on with your code. Maybe if you share your migration and the complete Listing class file it might be easier to spot what's going on.

Here are a few steps to make sure you got it right:

  1. Create a brand new rails app (you can delete it later):
rails new testrichtext -d mysql --api
  1. Create the db
cd testrichclient
rake db:create
  1. Create the model
rails g model listing description:text
  1. Change your newly created migration file to make sure the column is not null:
class CreateListings < ActiveRecord::Migration[6.0]
  def change
    create_table :listings do |t|
      t.text :description, null: false

      t.timestamps
    end
  end
end

  1. Run the migration
rake db:migrate
  1. Now you should be able to log in into the console, and create a new listing with something as the description:
rails c

And inside console:

l = Listing.new(description: "<p>Something nice</p>")
l.save!
Listing.first.description

As you can see, this is enough to save/seed a new listing with rich text. So anything you may have going on there should be something you're causing somewhere else, by adding a validation differently, or callbacks. Hard to say without looking at the entire file

0
Daniel Mendez On

I found this to work for me:

15.times do
  Post.create!(title: Faker::Book.unique.title)
end

then

Post.all.each do |post|
  ActionText::RichText.create!(record_type: 'Post', record_id: post.id, name: 'content', body: Faker::Lorem.sentence)
end

To read:

Post.first.content.body.to_plain_text 

or:

Post.first.content.body.to_trix_html

...as stated above by OP.

Source: https://linuxtut.com/rails6-input-the-initial-data-of-actiontext-using-seed-9b4f2/