我有以下型号:
class Site < ApplicationRecord
has_many :posts
end
class Post < ApplicationRecord
belongs_to :site
end
路线:
resources :posts, only: %i[create update]
还有我的控制器:
# frozen_string_literal: true
class PostsController < ApplicationController
before_action :set_post, only: [:update]
PERMITED_POST_PARAMS = [
:site_id,
:title,
:url,
:body,
].freeze
def create
@post = Post.new(post_params)
if @post.save
render json: @post, status: :created
else
render json: @post.errors, status: :unprocessable_entity
end
end
def update
if @post.update(post_params)
render json: @post
else
render json: @post.errors, status: :unprocessable_entity
end
end
private
def post_params
params.require(:post).permit(*PERMITED_POST_PARAMS)
end
def set_post
@post = Post.find(id)
end
def id
params[:id]
end
end
site_id
可以在更新时更改。是否可以将这个属性标记为仅在创建时分配,并在更新时引发错误?
在这种情况下,无需使用嵌套路由(/sites/:site_id/posts
和/sites/:site_id/posts/:id
),因为我知道我要更新的帖子的id
(因此属性{ {1}}仅用于创建帖子),我也更喜欢代码更独立的代码。
谢谢。
答案 0 :(得分:0)
如何使用不同的允许参数进行创建和更新:
def create_params
params.require(:post).permit(:site_id, :title, :url, :body)
end
def update_params
params.require(:post).permit(:title, :url, :body)
end
还有一件事,如果您使用的是嵌套路由,则不要从所有帖子(Post.find(params][:id])
)中找到帖子,而应该从属于site_id的帖子中找到它:@site = Site.find(params[:site_id]); @site.posts.find(params[:id])
>
答案 1 :(得分:0)
您可以使用ActionController::Parameters#except
:
# ...
def update
if @post.update(post_params.except(:site_id))
render json: @post
else
render json: @post.errors, status: :unprocessable_entity
end
end
或者您可以将基本参数提取到常量中,然后将其与每个动作参数合并:
# corrected the spelling.
PERMITTED_POST_PARAMS = %i{ title url body }.freeze
def create_params
params.require(:post).permit(:site_id, *PERMITTED_POST_PARAMS)
end
def update_params
params.require(:post).permit(*PERMITTED_POST_PARAMS)
end