如何防止关联在更新时发生更改

时间:2019-11-22 18:17:33

标签: ruby-on-rails ruby

我有以下型号:

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}}仅用于创建帖子),我也更喜欢代码更独立的代码。

谢谢。

2 个答案:

答案 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