I'm doing a Ruby on Rails API. I have two models plans
and categories
, which has a relation "many to many" so I use an intermediate table with a model called category_plans
. What I want is to create a plan with many categories, and each one of them has two more attributes (kind
, portion
) which will be saved on the intermediate table. (I'm using Postgresql).
Category
class Category < ApplicationRecord
has_many :category_plans
has_many :plan, through: :category_plans
end
Plan
class Plan < ApplicationRecord
has_many :category_plans
has_many :category, through: :category_plans
end
CategoryPlan
class CategoryPlan < ApplicationRecord
validates_presence_of :category, :plan
enum kind: {
Colacion: 'Colacion',
Desayuno: 'Desayuno',
Comida: 'Comida',
Cena: 'Cena'
}, _prefix: :kind
belongs_to :category
belongs_to :plan
end
These are the migrations I use:
Plan
class CreatePlans < ActiveRecord::Migration[5.2]
def change
create_table :plans do |t|
t.string :name
t.references :patient, foreign_key: true
t.text :description
t.datetime :deleted_at
t.timestamps
end
end
end
Category
class CreateCategories < ActiveRecord::Migration[5.2]
def change
create_table :categories do |t|
t.string :name
t.timestamps
end
end
end
CategoryPlan
class CreateCategoryPlans < ActiveRecord::Migration[5.2]
def up
execute <<-SQL
CREATE TYPE type_food AS ENUM ('Colacion', 'Desayuno', 'Comida',
'Cena');
SQL
create_table :category_plans do |t|
t.belongs_to :category, :null => false, :index => true
t.belongs_to :plan, :null => false, :index => true
t.column :kind , :type_food
t.float :portion
end
add_index :category_plans, :kind
end
def down
drop_column :kind, :type_food
execute "DROP kind type_food;"
end
end
And the controller:
class V1::PlansController < ApplicationController
before_action :set_patient, only: [:show, :update, :destroy]
def create
plan = Plan.new(plan_params)
if plan.save
render json: {status: 'Success', message: 'Saved plan', data:
plan}, status: 201
else
render json: {status: 'Error', message: 'Plan not saved', data:
plan.errors}, status: :unprocessable_entity
end
end
def plan_params
params.require(:plan).permit(:name, :patient_id, :description,
category_plans_attributes: [:id, :kind, :portion,
category_attributes: [:id]])
end
end
I'm not sure that "strong params" is right, also I'm not sure about how to do my JSON structure, at this time I got it like this:
JSON
{
"plan": {
"name": "Plan 8",
"patient_id": "3",
"description": "Plan nuevo",
"category_plan": {
"kind": "Cena",
"portion": "12.3"
}
}
}