Search code examples
ruby-on-railsactiverecordassociationsmodel-associationsruby-on-rails-7

Rails: Create a form which adds another referencing model


I have a Rating Table which contains a Explanation Field (text). I would like to have one form which creates both entries (in SasRating and in TextContent).

My Code:

Migrates:

class CreateSasRatings < ActiveRecord::Migration[7.0]
  def change
    create_table :sas_ratings do |t|
      t.string :rating
      t.references :explanation
      t.references :sas, null: false, foreign_key: true

      t.timestamps
    end
  end
end
class CreateTextContents < ActiveRecord::Migration[7.0]
  def change
    create_table :text_contents do |t|
      t.text :originaltext
      t.references :originaltext_language

      t.timestamps
    end
  end
end

Models:

class SasRating < ApplicationRecord
  belongs_to :explanation, :class_name => :TextContent
  belongs_to :sas
end
class TextContent < ApplicationRecord
  belongs_to :originaltext_language, :class_name => "Language"
end

Controller:

class SasRatingsController < ApplicationController
  def new
    @sas = Sas.find(params[:id])
    @sasrating = SasRating.new
  end

  def create
    @sasrating = SasRating.new(sas_rating_params)
    @sasrating.create_explanation(originaltext: sas_rating_params[:explanation], originaltext_language: sas_rating_params[:originaltext_language] )

    @sasrating.save!
    flash[:notice] = "SAS Rating was created successfully."
    redirect_to sas_path(sas_rating_params[:sas])
  rescue => e
    logger.error(e.to_s)
    flash.now[:danger] = "SAS Rating could not be saved: #{e.to_s}"
    render 'new'
  end

  private

  def set_sasrating
    @sas = SasRating.find(params[:id])
  end

  def sas_rating_params
    params.require(:sas_rating).permit(:rating, :explanation, :language, :sas_id)
  end
end

new.html.erb:

    <%= form_with model: @sasrating, local: true do |f| %>
      <p> 
        <%= f.label :rating, class: "form-label" %><br/> 
        <%= f.number_field :rating, class: "form-control" %>
      </p>
      <p>
        <%= fields_for :explanation, @sasrating.explanation do |e| %>
          <%= e.label :explanation, class: "form-label" %><br/> 
          <%= e.text_field :originaltext, class: "form-control" %>
          <%= e.hidden_field :originaltext_language, :value => 2 %>
        <% end %>
      </p>
      <p>
        <%= f.hidden_field :sas_id, :value => params[:id] %>
        <%= f.submit "submit", class: "btn btn-primary" %> 
      </p>
    <% end %>

Currently, it's saving SasRating, but without Explanation. What am I doing wrong?

Thanks in advance.


Solution

  • -To create Explanation object along with SasRating, you need to use accepts_nested_attributes_for in the SasRating model, e.g. accepts_nested_attributes_for :explanation