簡體   English   中英

Rails - 在has_many表上插入

[英]Rails - Insert on a has_many through table

我有兩個類,用戶和機會,它們使用具有has_many:through關系的連接表,以允許用戶注冊一個到多個機會(並允許一個機會讓很多用戶注冊)。

class User < ApplicationRecord
  has_many :opportunity_enrolments, :class_name => 'OpportunityEnrolment', foreign_key: "user_id"
  has_many :opportunities, through: :opportunity_enrolments, foreign_key: "opportunity_id"
  has_secure_password
  validates :email, presence: true, uniqueness: true
end
class Opportunity < ApplicationRecord
  has_many :opportunity_enrolments, :class_name => 'OpportunityEnrolment'
  has_many :users, through: :opportunity_enrolments
end
class OpportunityEnrolment < ApplicationRecord
  belongs_to :opportunity
  belongs_to :user
end

只有當用戶和機會都存在時,用戶才會注冊機會。 因此,注冊功能將在創建用戶和機會之外進行,這些功能將單獨發生並且正常工作。 我認為我可以在查看商機時使用OpportunityEnrolment.create方法,以使用下面的表單和控制器向opportunity_enrolments表添加新行。

機會/ show.html.erb

<%= form_with(model: OpportunityEnrolment.create, local: true) do |form| %>
<p>
  <strong>Name:</strong>
  <%= @opportunity.voppname %>
</p>
<p>
  <strong>Shortdescr:</strong>
  <%= @opportunity.shortdescr %>
</p>
<p>
  <%= form.submit %>
</p>
<% end %>

opportunity_enrolments_controller.rb

def create      
   @opportunity_enrolment = OpportunityEnrolment.new(user_id: current_user.id, opportunity_id: @opportunity.id)

  error checking and .save...
end

但是,我的表單中的@ opportunity.id沒有被傳遞給OpportunityEnrolment.create方法,因此我在提交時收到“nil:NilClass的未定義方法`id'錯誤”。 我用不同的方式嘗試了它,在表單中有一個隱藏字段(理解它不安全)並且對象仍然沒有通過,但是我超過了Undefined方法錯誤。

如何將對象信息(Opportunity)傳遞給另一個類(OpportunityEnrolments),以便我可以在opportunity_enrolments表中添加一行?

謝謝

這應該使用嵌套路由而不是在表單中傳遞機會ID。

# config/routes.rb
Rails.application.routes.draw do

  # create the route: GET /opportunities/:id
  # helper: opportunity_path(opportunity || opportunity_id)
  # handled by: OpportunitiesController#show
  resources :opportunities, only: :show do

    # create the route: POST /opportunities/:opportunity_id/opportunity_enrolments
    # helper: opportunity_opportunity_enrolments_path(opportunity || opportunity_id)
    # handled by: OpportunityEnrolmentsController#create
    resources :opportunity_enrolments, only: :create
  end

end

# app/controllers/opportunity_enrolments_controller.rb
class OpportunityEnrolmentsController < ApplicationController
  # opportunity should be set for every nested action, create in this scenario
  before_action :set_opportunity, only: :create

  def create
    # initialize a new opportunity enrolment with opportunity id set to
    # the id of the current opportunity
    @opportunity_enrolment = @opportunity.opportunity_enrolments.build
    # set the user id equal to the current user
    @opportunity_enrolment.user = current_user

    # assign the passed attributes by the form and try to save the record
    # if your form doesn't contain any attributes, call #save instead
    if @opportunity_enrolment.update(opportunity_enrolment_params)
      redirect_to @opportunity
    else
      # display errors using @opportunity_enrolment.errors in the form, see note
      render 'opportunities/show' 
    end
  end

  private

  def opportunity_enrolment_params
    # if you only need to set the attributes opportunity_id and user_id
    # you can leave this call out and call #save instead of #update
    # ...
  end

  def set_opportunity
    # params[:opportunity_id] is retrieved from the current path, it is not
    # a query or request body param
    @opportunity = Opportunity.find(params[:opportunity_id])
  end
end

<% # app/views/opportunities/show.html.erb %>

<% # If rendered from opportunity show: opportunity enrolment is not set thus a new     %>
<% # opportunity enrolment will be initialized. If rendered from the opportunity        %>
<% # enrolment create action: opportunity enrolment will already be present with errors %>
<% # set, no new opportunity will be initialized.                                       %>
<% @opportunity_enrolment ||= @opportunity.opportunity_enrolments.build %>

<% # Passing an array containing an opportunity and an opportunity enrolment will build  %>
<% # the path in 3 steps. 1) Is opportunity a new record? Use /opportunities, if not use %>
<% # /opportunities/:id. 2) Is opportunity enrolment a new record? Use                   %>
<% # /opportunity_enrolments, if not use /opportunity_enrolments/:id. 3) Is the last     %>
<% # element in the array a new record? Use POST, if not use PUT.                        %>
<% # Combining the above together you get the path:                                      %>
<% # POST /opportunities/:opportunity_id/opportunity_enrolments                          %>
<% # Handled by OpportunityEnrolmentsController#create (see routes).                     %>
<%= form_with model: [@opportunity, @opportunity_enrolment], local: true do |form| %>
  <p><strong>Name:</strong><%= @opportunity.voppname %></p>
  <p><strong>Shortdescr:</strong><%= @opportunity.shortdescr %></p>
  <p><%= form.submit %></p>
<% end %>

注意 :如果您要閱讀嵌套資源,請不要跳過有關淺嵌套的部分。 它使您的路線和應用程序更清潔。 可在此處找到錯誤訪問頁面。

如果使用隱藏字段,則需要在opportunity_enrolments_controller中的create動作中實例化機會。

def create
  @opportunity = Opportunity.find(params[:opportunity_id])
  @opportunity_enrolment = OpportunityEnrolment.new(user_id: current_user.id, opportunity_id: @opportunity.id)
end

形式如下:

<%= form_with(model: OpportunityEnrolment.create, local: true) do |form| %>
<p>
  <strong>Name:</strong>
  <%= @opportunity.voppname %>
</p>
<p>
  <strong>Shortdescr:</strong>
  <%= @opportunity.shortdescr %>
  <%= form.hidden_field :opportunity_id, value: @opportunity.id %>
</p>
<p>
  <%= form.submit %>
</p>
<% end %>

暫無
暫無

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

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