ruby-on-railsactiontextadministrate

How to Setup ActionText in Administrate (Rails 6.1)


I'm trying to set up Action Text inside an Administrate Dashboard. I've followed the installation steps on the Rails Guides Overview page. Then when trying to add the attribute to /app/dashboards/lesson_dashboard.rb, I get errors.

When I try body: Field::RichText, I get: uninitialized constant Administrate::Field::RichText

When I try body: ActionText::RichText, I get: wrong number of arguments (given 4, expected 0..1).

When I follow the instructions in the Administrate Wiki, I get undefined method 'body' when it gets to the line with <%= f.rich_text_area field.attribute %>.

Any idea what this attribute is called or why I'm getting these errors?

app/dashboards/lesson_dashboard.rb:

require "administrate/base_dashboard"

class LessonDashboard < Administrate::BaseDashboard
  # ATTRIBUTE_TYPES
  # a hash that describes the type of each of the model's fields.
  #
  # Each different type represents an Administrate::Field object,
  # which determines how the attribute is displayed
  # on pages throughout the dashboard.
  ATTRIBUTE_TYPES = {
    course: Field::BelongsTo,
    documents: Field::ActiveStorage.with_options(
      show_display_preview: false,
      destroy_url: proc do |namespace, resource, document|
        [:delete_document_course, resource, { document_id: document.id }]
      end
    ),
    id: Field::Number,
    title: Field::String,
    # body: Field::Text,
    body: RichTextAreaField,
    created_at: Field::DateTime,
    updated_at: Field::DateTime,
  }.freeze

  # COLLECTION_ATTRIBUTES
  # an array of attributes that will be displayed on the model's index page.
  #
  # By default, it's limited to four items to reduce clutter on index pages.
  # Feel free to add, remove, or rearrange items.
  COLLECTION_ATTRIBUTES = %i[
    title
    course
  ].freeze

  # SHOW_PAGE_ATTRIBUTES
  # an array of attributes that will be displayed on the model's show page.
  SHOW_PAGE_ATTRIBUTES = %i[
    course
    title
    body
    documents
    created_at
    updated_at
  ].freeze

  # FORM_ATTRIBUTES
  # an array of attributes that will be displayed
  # on the model's form (`new` and `edit`) pages.
  FORM_ATTRIBUTES = %i[
    course
    title
    body
    documents
  ].freeze

  # COLLECTION_FILTERS
  # a hash that defines filters that can be used while searching via the search
  # field of the dashboard.
  #
  # For example to add an option to search for open resources by typing "open:"
  # in the search field:
  #
  #   COLLECTION_FILTERS = {
  #     open: ->(resources) { resources.where(open: true) }
  #   }.freeze
  COLLECTION_FILTERS = {}.freeze

  # Overwrite this method to customize how lessons are displayed
  # across all pages of the admin dashboard.
  def display_resource(lesson)
    lesson.title
  end

  # permitted for has_many_attached
  def permitted_attributes
    # super + [:attachments => []]
    super + [:documents => []]
  end

end

app/models/lesson.rb:

class Lesson < ApplicationRecord

  belongs_to :course
  has_many_attached :documents

  validates :title, presence: true

end

Solution

  • The ActionText guide and Administrate help have the information, but it is somewhat disjointed across multiple pages, so I've jotted down the steps I used on a fresh Rails 6.1 application.

    These steps assume that you have configured ActionText (run rails g action_text:install and run the resulting migrations), and installed/configured the administrate gem.

    1. The Trix rich text editor requires Javascript, which in Rails 6 is loaded with webpack. The default administrate layout isn't webpack-friendly, so you need to customise the layout. Generate layouts to customise:
      % rails generate administrate:views:layout
    
    1. Add a javascript_pack_tag to views/layouts/admin/application.html.erb to load your application pack:
    <head>
    ...
      <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
      <%= render "stylesheet" %>
      <%= csrf_meta_tags %>
    ...
    </head>
    

    The administrate guide steps you through creating a separate pack for administrate JS, but it's only required if you need to customise the JS (e.g., for using flatpickr as date picker). For just using RichText it isn't required, so we just load the main application pack.

    1. You also need to customise the administrate CSS to add the Trix styles. Run the task to generate the custom administrate stylesheets:
    % rails generate administrate:assets:stylesheets
    
    1. Edit administrate stylesheets to include styles for the Trix rich text controls at the bottom:
    // Rest of file
    ...
    @import "trix/dist/trix";
    @import "selectize";
    
    .trix-content {
      .attachment-gallery {
        > action-text-attachment,
        > .attachment {
          flex: 1 0 33%;
          padding: 0 0.5em;
          max-width: 33%;
        }
    
        &.attachment-gallery--2,
        &.attachment-gallery--4 {
          > action-text-attachment,
          > .attachment {
            flex-basis: 50%;
            max-width: 50%;
          }
        }
      }
    
      action-text-attachment {
        .attachment {
          padding: 0 !important;
          max-width: 100% !important;
        }
      }
    }
    
    .field-unit--rich-text-area-field {
      .field-unit__field {
        width: 80%;
      }
    }
    
    1. Add a custom field type for rich text editing since Administrate doesn't include one out of the box.
    % rails g administrate:field rich_text_area
    
    1. Edit the input field type in fields/rich_text_area/_form.html.erb to use the Trix rich text control:
    <div class="field-unit__field">
      <%= f.rich_text_area field.attribute %>
    </div>
    
    1. Edit your model to add your rich text attribute:
    class Lesson < ApplicationRecord
      has_rich_text :body
    end
    
    1. Generate a dashboard for your model:
    % rails generate administrate:dashboard Lesson
    
    1. Edit the field type in dashboards/lesson_dashboard.rb to use the custom field type:
      ATTRIBUTE_TYPES = {
        ...
        rich_text_body: RichTextAreaField,
      }.freeze
    
    1. Profit: enter image description here