是否有建议的方法在 RoR 中创建嵌套的多对多实体,避免嵌套资源的 JSON 字段中的 *_attributes?
Is there a suggested way to create nested many-to-many entities in RoR that avoids *_attributes in the JSON field for the nested resource?
我已经成功地通过使用 accepts_nested_attributes_for
为 JSON 和下面的项目创建了嵌套的多对多实体。
我的问题是 - 是否有建议的方法来实现相同的事情,我不必添加 _attributes
就能够在 RoR 服务器上创建 emotion
对象数组?我所说的建议的意思是框架本身建议的东西,或者尽可能干净的东西。
JSON 得到 posted 到 http://localhost:3000/periods:
{
"period": {
"date": "2022-03-17T03:00:52.820Z",
"period": "morning",
"emotions_attributes": [
{
"name": "ok"
},
{
"name": "fine"
}
]
}
}
rails generate
用于创建后续文件的命令:
rails g model Emotion name:string
rails g scaffold Period date:date period:string --skip-template-engine
rails g scaffold Entry emotion:references period:references --skip-template-engine
periods.rb:
class Period < ApplicationRecord
has_many :entries
has_many :emotions, through: :entries
accepts_nested_attributes_for :emotions
end
emotion.rb
class Emotion < ApplicationRecord
has_many :entries
has_many :periods, through: :entries
end
entry.rb
class Entry < ApplicationRecord
belongs_to :emotion
belongs_to :period
end
periods_controller.rb
class PeriodsController < ApplicationController
before_action :set_period, only: %i[ show edit update destroy ]
skip_before_action :verify_authenticity_token
...
def create
@period = Period.new(period_params)
respond_to do |format|
if @period.save
format.html { redirect_to period_url(@period), notice: "Period was successfully created." }
format.json { render :show, status: :created, location: @period }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: @period.errors, status: :unprocessable_entity }
end
end
end
...
# FYI turns out the id is key here to be able to even perform create
def period_params
params.require(:period).permit(
:date,
:period,
emotions_attributes: [:id, :name]
)
end
routes.rb
Rails.application.routes.draw do
resources :entries
resources :periods
我希望能够 post 是这样的:
{
"period": {
"date": "2022-03-17T03:00:52.820Z",
"period": "morning",
"emotions": [
{
"name": "ok"
},
{
"name": "fine"
}
]
}
}
您不会找到实现该目标的更简洁方法,因为“emotions_attributes”由框架“开箱即用”处理。
或者,您可以创建一个服务对象以创建更多自定义周期 (fe app/services/periods/create.rb) 并从控制器调用它。这样您就可以自定义默认约定并将逻辑放在一个地方。
但是恕我直言,只要您刚刚开始使用 rails 并且主要担心的是“情绪看起来比 emotions_attributes 更好”,您就应该保持默认约定。
好吧,你可以像这样允许你的参数:
def period_params_hand
params.require(:period).permit(
:date,
:period,
emotions: [:id, :name]
)
end
然后您可以在#create 中做的第一件事是:
# receive the permitted params
period_params = period_params_hand
# rename the hash key
period_params[:emotions_attributes] = period_params.delete(:emotions)
这是实现您的目标的一种方法,但回答您的问题时,没有建议的方法。
我已经成功地通过使用 accepts_nested_attributes_for
为 JSON 和下面的项目创建了嵌套的多对多实体。
我的问题是 - 是否有建议的方法来实现相同的事情,我不必添加 _attributes
就能够在 RoR 服务器上创建 emotion
对象数组?我所说的建议的意思是框架本身建议的东西,或者尽可能干净的东西。
JSON 得到 posted 到 http://localhost:3000/periods:
{
"period": {
"date": "2022-03-17T03:00:52.820Z",
"period": "morning",
"emotions_attributes": [
{
"name": "ok"
},
{
"name": "fine"
}
]
}
}
rails generate
用于创建后续文件的命令:
rails g model Emotion name:string
rails g scaffold Period date:date period:string --skip-template-engine
rails g scaffold Entry emotion:references period:references --skip-template-engine
periods.rb:
class Period < ApplicationRecord
has_many :entries
has_many :emotions, through: :entries
accepts_nested_attributes_for :emotions
end
emotion.rb
class Emotion < ApplicationRecord
has_many :entries
has_many :periods, through: :entries
end
entry.rb
class Entry < ApplicationRecord
belongs_to :emotion
belongs_to :period
end
periods_controller.rb
class PeriodsController < ApplicationController
before_action :set_period, only: %i[ show edit update destroy ]
skip_before_action :verify_authenticity_token
...
def create
@period = Period.new(period_params)
respond_to do |format|
if @period.save
format.html { redirect_to period_url(@period), notice: "Period was successfully created." }
format.json { render :show, status: :created, location: @period }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: @period.errors, status: :unprocessable_entity }
end
end
end
...
# FYI turns out the id is key here to be able to even perform create
def period_params
params.require(:period).permit(
:date,
:period,
emotions_attributes: [:id, :name]
)
end
routes.rb
Rails.application.routes.draw do
resources :entries
resources :periods
我希望能够 post 是这样的:
{
"period": {
"date": "2022-03-17T03:00:52.820Z",
"period": "morning",
"emotions": [
{
"name": "ok"
},
{
"name": "fine"
}
]
}
}
您不会找到实现该目标的更简洁方法,因为“emotions_attributes”由框架“开箱即用”处理。
或者,您可以创建一个服务对象以创建更多自定义周期 (fe app/services/periods/create.rb) 并从控制器调用它。这样您就可以自定义默认约定并将逻辑放在一个地方。
但是恕我直言,只要您刚刚开始使用 rails 并且主要担心的是“情绪看起来比 emotions_attributes 更好”,您就应该保持默认约定。
好吧,你可以像这样允许你的参数:
def period_params_hand
params.require(:period).permit(
:date,
:period,
emotions: [:id, :name]
)
end
然后您可以在#create 中做的第一件事是:
# receive the permitted params
period_params = period_params_hand
# rename the hash key
period_params[:emotions_attributes] = period_params.delete(:emotions)
这是实现您的目标的一种方法,但回答您的问题时,没有建议的方法。