首页 > 解决方案 > 我应该如何更新完全依赖于其他资源的资源

问题描述

假设我有这两个模型:

class Post < ApplicationRecord
  belongs_to :site
end

class Site < ApplicationRecord
  has_many :posts
end

为了创建帖子,我需要知道站点 ID。现在我有一条指向 PostsController#create

post 'posts', to: 'posts#update'

我应该期望用户site_id在请求的正文中发送吗?

标签: ruby-on-rails

解决方案


# config/routes.rb
resources :sites do
  resources :posts
end

这会创建嵌套路由。运行$ rails routes以查看创建的路由。

我应该期望用户在请求正文中发送 site_id 吗?

不会。嵌套路由描述了两个资源之间的关系。通过查看POST /sites/1/posts将创建属于站点的帖子的路径,它非常明显。

如果您使用浅嵌套,则可以在参数中传递站点 ID,并且用户可以在更新时更改帖子所属的站点。

# app/controllers/posts_controller.rb
class PostsController
  before_action :set_site
  before_action :set_post, only: [:show, :edit, :update]

  # GET /sites/1/posts/1
  def show
  end

  # GET /sites/1/posts
  def index
    @posts = @site.posts
  end

  # GET /sites/1/posts/new
  def new
    @post = @site.posts.new
  end

  # POST /sites/1/posts
  def create
    @post = @site.posts.new(post_params)
    if @post.save
      redirect_to @post
    else
      render :new
    end
  end

  # PATCH|PUT /sites/1/posts
  def update
    if @post.update(post_params)
      redirect_to @post
    else
      render :edit
    end
  end

  # GET /sites/1/posts/edit
  def edit
  end

  private
  def set_site
    @site = Site.includes(:posts).find(params[:site_id])
  end

  def set_post
    @post = @site.posts.find(params[:id])
  end

  def post_params
    params.require(:post).permit(:title) # ...
  end
end
# app/views/posts/_form.html.erb
<%= form_for [@site, @post] do |f| %>
  # ...
<% end %>

# app/views/posts/new.html.erb
<%= render partial: 'form' %>

# app/views/posts/edit.html.erb
<%= render partial: 'form' %>

推荐阅读