title: How to save a nested many-to-many relationship in API-only Rails?
body: <p>In my Rails (api only) learning project, I have 2 models, Group and Artist, that have a many-to-many relationship with a joining model, Role, that has additional information about the relationship. I have been able to save m2m relationships before by saving the joining model by itself, but here I am trying to save the relationship as a nested relationship. I'm using the <a href="https://github.com/jsonapi-serializer/jsonapi-serializer" rel="nofollow noreferrer">jsonapi-serializer</a> gem, but not married to it nor am I tied to the JSON api spec. Getting this to work is more important than following best practice.</p>
  <p>With this setup, I'm getting a 500 error when trying to save with the following errors:
  <code>Unpermitted parameters: :artists, :albums</code> and <code>ActiveModel::UnknownAttributeError (unknown attribute 'relationships' for Group.)</code></p>
  <p>I'm suspecting that my problem lies in the strong param and/or the json payload.</p>
  <p><strong>Models</strong></p>
  <pre><code>class Group &lt; ApplicationRecord
    has_many :roles
    has_many :artists, through: :roles
  
    accepts_nested_attributes_for :artists, :roles
  end
  
  
  class Artist &lt; ApplicationRecord
    has_many :groups, through: :roles
  end
  
  
  class Role &lt; ApplicationRecord
    belongs_to :artist
    belongs_to :group
  end
  
  </code></pre>
  <p><strong>Controller#create</strong></p>
  <pre><code>def create
    group = Group.new(group_params)
  
    if group.save
      render json: GroupSerializer.new(group).serializable_hash
    else
      render json: { error: group.errors.messages }, status: 422
    end
  end
  </code></pre>
  <p><strong>Controller#group_params</strong></p>
  <pre><code>def group_params
    params.require(:data)
      .permit(attributes: [:name, :notes],
        relationships: [:artists])
  end
  </code></pre>
  <p><strong>Serializers</strong></p>
  <pre><code>class GroupSerializer
    include JSONAPI::Serializer
    attributes :name, :notes
  
    has_many :artists
    has_many :roles
  end
  
  
  class ArtistSerializer
    include JSONAPI::Serializer
    attributes :first_name, :last_name, :notes
  end
  
  
  class RoleSerializer
    include JSONAPI::Serializer
    attributes :artist_id, :group_id, :instruments
  end
  </code></pre>
  <p><strong>Example JSON payload</strong></p>
  <pre><code>{
    &quot;data&quot;: {
      &quot;attributes&quot;: {
        &quot;name&quot;: &quot;Pink Floyd&quot;,
        &quot;notes&quot;: &quot;&quot;,
      },
      &quot;relationships&quot;: {
        &quot;artists&quot;: [{ type: &quot;artist&quot;, &quot;id&quot;: 3445 }, { type: &quot;artist&quot;, &quot;id&quot;: 3447 }]
      }
  }
  </code></pre>
  <p><strong>Additional Info</strong></p>
  <p>It might help to know that I was able to save another model with the following combination of json and strong params.</p>
  <pre><code># Example JSON
  
  &quot;data&quot;: {
    &quot;attributes&quot;: {
      &quot;title&quot;: &quot;Wish You Were Here&quot;,
      &quot;release_date&quot;: &quot;1975-09-15&quot;,
      &quot;release_date_accuracy&quot;: 1
      &quot;notes&quot;: &quot;&quot;,
      &quot;group_id&quot;: 3455
    }
  }
  
  
  # in albums_controller.rb 
  
  def album_params
    params.require(:data).require(:attributes)
      .permit(:title, :group_id, :release_date, :release_date_accuracy, :notes)
  end
  </code></pre>