簡體   English   中英

具有強大參數的 Rails 6 嵌套資源

[英]Rails 6 nested resources with strong params

我在 Rails 應用程序中嵌套了資源,基本上一個ProjectTargets ,我認為創建關系的最簡單方法是在我的 routes.rb 中執行此操作:

resource :projects do
  resource :targets
end

我的模型也非常匹配:

- Project.rb
class Project < ApplicationRecord
  has_many :targets
end

- Target.rb
class Target < ApplicationRecord
  has_one :project
end

運行rake routes向我展示了我的期望:

project_targets GET    /projects/:project_id/targets(.:format)                                                  targets#index
                                      POST   /projects/:project_id/targets(.:format)                                                  targets#create
                   new_project_target GET    /projects/:project_id/targets/new(.:format)                                              targets#new
                  edit_project_target GET    /projects/:project_id/targets/:id/edit(.:format)                                         targets#edit
                       project_target GET    /projects/:project_id/targets/:id(.:format)                                              targets#show
                                      PATCH  /projects/:project_id/targets/:id(.:format)                                              targets#update
                                      PUT    /projects/:project_id/targets/:id(.:format)                                              targets#update
                                      DELETE /projects/:project_id/targets/:id(.:format)                                              targets#destroy
                             projects GET    /projects(.:format)                                                                      projects#index
                                      POST   /projects(.:format)                                                                      projects#create
                          new_project GET    /projects/new(.:format)                                                                  projects#new
                         edit_project GET    /projects/:id/edit(.:format)                                                             projects#edit
                              project GET    /projects/:id(.:format)                                                                  projects#show
                                      PATCH  /projects/:id(.:format)                                                                  projects#update
                                      PUT    /projects/:id(.:format)                                                                  projects#update
                                      DELETE /projects/:id(.:format)                                                                  projects#destroy

完成此操作后,我的創建/編輯表單不再適用於target ,因此我必須從以下位置調整form_for的第一行:

<%= form_for @target do |f| %>

to

<%= form_for @target, url: project_targets_path do |f| %>

注意我必須明確聲明網址

Target控制器中的 create 方法非常基本:

def create
  @target = Target.create(target_params)
  if @target.valid?
    redirect_to project_target_path(id: @target.id)
  else
    flash[:errors] = @target.errors.full_messages
    redirect_to new
  end
end

我嘗試創建一個目標是成功的,但根據 db 架構,該目標沒有分配給它的project_id

create_table :targets do |t|
  t.string :domain
  t.boolean :investigated, default: false
  t.boolean :research, default: false
  t.integer :project_id
  t.timestamps
end

這是我在日志中看到的,顯然project_id作為 URL 的一部分被傳遞,但它沒有與創建時的新目標相關聯。

Started POST "/projects/1/targets" for ::1 at 2020-03-13 19:19:57 -0400
Processing by TargetsController#create as HTML
  Parameters: {"authenticity_token"=>"jLzQmpsxMRW4z66WguFVwZcLnMxFJYIy86EDfru6fIhysWDU/fd6yq5HV2uv1Z3TICGQSAXZDll66DwizReWaQ==", "target"=>{"domain"=>"2-test.com"}, "commit"=>"Create", "project_id"=>"1"}
   (0.1ms)  begin transaction
  ↳ app/controllers/targets_controller.rb:11:in `create'
  Target Create (0.8ms)  INSERT INTO "targets" ("domain", "created_at", "updated_at") VALUES (?, ?, ?)  [["domain", "2-test.com"], ["created_at", "2020-03-13 23:19:57.097233"], ["updated_at", "2020-03-13 23:19:57.097233"]]
  ↳ app/controllers/targets_controller.rb:11:in `create'
   (1.1ms)  commit transaction
  ↳ app/controllers/targets_controller.rb:11:in `create'

我的設置不正確嗎? 如何解決此問題,以便在創建新目標時包含project_id 如果可能的話,我想保留這個 RESTful 並且不傳遞隱藏字段。

將表格設置為:

<%= form_for [@project, @target] do |f| %>

雖然您可以顯式傳遞一個 url:

<%= form_for @target, url: project_targets_path(@project) do |f| %>

如果您以部分形式共享表單,這將破壞editupdate操作,因為update操作屬性應指向/projects/:project_id/targets/:id 更喜歡約定而不是配置。

你的 create 方法在很多方面也被破壞了。

class TargetsController < ApplicationController
  before_action :set_project
  before_action :set_target, except: [:new, :index]

  # POST /projects/1/targets
  def create
    # building the new record off the parent sets the project_id
    @target = @project.targets.new(target_params)
    if @target.save
      redirect_to [@project, @target] 
    else
      flash[:errors] = @target.errors.full_messages
      # When a record is invalid always render - never redirect.
      render :new
    end
  end

  private
  def set_project
    @project = Project.find(params[:project_id])
  end
  # ...
end

if @project.valid? 只檢查應用程序驗證是否已通過 - 而不是記錄是否實際保存到數據庫中。 檢查@target.save@target.persisted? @target.save的返回值@target.persisted? 做。

請注意, :project_id不應包含在您的參數白名單中,因為它通過 url 而不是通過批量分配。 嵌套路由確實與強參數沒有任何關系。

您還應該閱讀 淺層嵌套,因為您很可能不需要嵌套成員路由,並且它大大降低了復雜性。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM