[英]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.