belongs_to 多个模型 Rails 的模型的 CRUD 方法
CRUD method for a model that belongs_to many models Rails
我是 Rails 的新手,我可能遗漏了一些非常基本的东西:
用户可以为公司的分支机构和部门创建联系人
Branch.rb
class Branch < ApplicationRecord
belongs_to :company
has_many :contacts
end
Division.rb
class Division < ApplicationRecord
belongs_to :company
has_many :contacts
end
Contact.rb
class Contact < ApplicationRecord
belongs_to :branch
belongs_to :division
end
现在用户可以从没有 division_id 的分支页面创建联系人,并且可以从部门页面创建联系人。
我这样定义我的 routes.rb:
Routes.rb
resources :companies, :shallow => true do
get 'company_page'
resources :branches, :shallow => true do
get 'branch_page'
resources :contacts
end
resources :divisions, :shallow => true do
get 'division_page'
resources :contacts
end
end
因此,如果我从 Branch 或 Division 创建联系人,它将转到 contacts#create 方法。
在我的 contacts_controller.rb 中,我有:
def create
@newContact = Contact.new(contact_params)
id = @division = @branch = nil
isBranch = false
if params[:branch_id] != nil
isBranch = true
id = params[:branch_id]
else
isBranch = false
id = params[:division_id]
end
if isBranch
branch = Branch.find(id)
@newContact.branch = branch
@branch = branch
else
division = Division.find(id)
@newContact.division = division
@division = division
end
respond_to do |format|
if @newContact.save
format.js
format.html { render :nothing => true, :notice => 'Contact created successfully!' }
format.json { render json: @newContact, status: :created, location: @newContact }
else
format.html { render action: "new" }
format.json { render json: @newContact, status: :unprocessable_entity }
end
end
end
但我在 @newContact.save
期间面对 ActiveRecord Error
。
我确定我在这里做的事情根本上是错误的,Rails 以另一种我不知道的优雅方式处理这些事情。
如@Anthony 所述,您需要将 belongs_to
关联设置为可选:
# app/models/contact.rb
class Contact < ApplicationRecord
belongs_to :branch, optional: true
belongs_to :division, optional: true
end
但另一个问题是 params[:division_id]
和 params[:branch_id]
总是 nil。这两个键都存在于 [:contact]
键中。所以你得到的错误应该是 ActiveRecord::RecordNotFound: Couldn't find Division with 'id'=
所有这些条件逻辑都是不必要的。您可以与给定的任何参数建立新的联系。此外,您应该使用 Ruby 变量命名约定,即 snake_case 而不是驼峰命名。
最后,我假设您希望将 HTML 请求重定向到分支或部门显示页面,具体取决于相关联的页面。所以我添加了逻辑来做到这一点。
这里是控制器的快速重构 #create
操作:
def create
@new_contact = Contact.new(contact_params)
if @new_contact.save
branch = @new_contact.branch
division = @new_contact.division
redirect_path = branch ? branch_path(branch) : division_path(division)
respond_to do |format|
format.js
format.html { redirect_to redirect_path, :notice => 'Contact created successfully!' }
format.json { render json: @new_contact, status: :created, location: @new_contact }
end
else
respond_to do |format|
format.html { render action: "new" }
format.json { render json: @new_contact, status: :unprocessable_entity }
end
end
end
这证明它有效:
# spec/controllers/contacts_controller_spec.rb
require 'rails_helper'
RSpec.describe ContactsController, type: :controller do
let(:company) { Company.create!(name: 'Company Name') }
let(:division) { Division.create!(name: 'Division Name', company: company) }
let(:branch) { Branch.create!(name: 'Branch Name', company: company) }
describe '#create' do
context 'when created with a division id' do
let(:attributes) { {'division_id' => division.id, 'name' => 'Contact Name'} }
it 'creates a contact record and associates it with the division' do
expect(Contact.count).to eq(0)
post :create, params: {contact: attributes}
expect(Contact.count).to eq(1)
contact = Contact.first
expect(contact.division).to eq(division)
end
end
context 'when created with a branch id' do
let(:attributes) { {'branch_id' => branch.id, 'name' => 'Contact Name'} }
it 'creates a contact record and associates it with the branch' do
expect(Contact.count).to eq(0)
post :create, params: {contact: attributes}
expect(Contact.count).to eq(1)
contact = Contact.first
expect(contact.branch).to eq(branch)
end
end
end
end
我是 Rails 的新手,我可能遗漏了一些非常基本的东西:
用户可以为公司的分支机构和部门创建联系人
Branch.rb
class Branch < ApplicationRecord
belongs_to :company
has_many :contacts
end
Division.rb
class Division < ApplicationRecord
belongs_to :company
has_many :contacts
end
Contact.rb
class Contact < ApplicationRecord
belongs_to :branch
belongs_to :division
end
现在用户可以从没有 division_id 的分支页面创建联系人,并且可以从部门页面创建联系人。
我这样定义我的 routes.rb:
Routes.rb
resources :companies, :shallow => true do
get 'company_page'
resources :branches, :shallow => true do
get 'branch_page'
resources :contacts
end
resources :divisions, :shallow => true do
get 'division_page'
resources :contacts
end
end
因此,如果我从 Branch 或 Division 创建联系人,它将转到 contacts#create 方法。
在我的 contacts_controller.rb 中,我有:
def create
@newContact = Contact.new(contact_params)
id = @division = @branch = nil
isBranch = false
if params[:branch_id] != nil
isBranch = true
id = params[:branch_id]
else
isBranch = false
id = params[:division_id]
end
if isBranch
branch = Branch.find(id)
@newContact.branch = branch
@branch = branch
else
division = Division.find(id)
@newContact.division = division
@division = division
end
respond_to do |format|
if @newContact.save
format.js
format.html { render :nothing => true, :notice => 'Contact created successfully!' }
format.json { render json: @newContact, status: :created, location: @newContact }
else
format.html { render action: "new" }
format.json { render json: @newContact, status: :unprocessable_entity }
end
end
end
但我在 @newContact.save
期间面对 ActiveRecord Error
。
我确定我在这里做的事情根本上是错误的,Rails 以另一种我不知道的优雅方式处理这些事情。
如@Anthony 所述,您需要将 belongs_to
关联设置为可选:
# app/models/contact.rb
class Contact < ApplicationRecord
belongs_to :branch, optional: true
belongs_to :division, optional: true
end
但另一个问题是 params[:division_id]
和 params[:branch_id]
总是 nil。这两个键都存在于 [:contact]
键中。所以你得到的错误应该是 ActiveRecord::RecordNotFound: Couldn't find Division with 'id'=
所有这些条件逻辑都是不必要的。您可以与给定的任何参数建立新的联系。此外,您应该使用 Ruby 变量命名约定,即 snake_case 而不是驼峰命名。
最后,我假设您希望将 HTML 请求重定向到分支或部门显示页面,具体取决于相关联的页面。所以我添加了逻辑来做到这一点。
这里是控制器的快速重构 #create
操作:
def create
@new_contact = Contact.new(contact_params)
if @new_contact.save
branch = @new_contact.branch
division = @new_contact.division
redirect_path = branch ? branch_path(branch) : division_path(division)
respond_to do |format|
format.js
format.html { redirect_to redirect_path, :notice => 'Contact created successfully!' }
format.json { render json: @new_contact, status: :created, location: @new_contact }
end
else
respond_to do |format|
format.html { render action: "new" }
format.json { render json: @new_contact, status: :unprocessable_entity }
end
end
end
这证明它有效:
# spec/controllers/contacts_controller_spec.rb
require 'rails_helper'
RSpec.describe ContactsController, type: :controller do
let(:company) { Company.create!(name: 'Company Name') }
let(:division) { Division.create!(name: 'Division Name', company: company) }
let(:branch) { Branch.create!(name: 'Branch Name', company: company) }
describe '#create' do
context 'when created with a division id' do
let(:attributes) { {'division_id' => division.id, 'name' => 'Contact Name'} }
it 'creates a contact record and associates it with the division' do
expect(Contact.count).to eq(0)
post :create, params: {contact: attributes}
expect(Contact.count).to eq(1)
contact = Contact.first
expect(contact.division).to eq(division)
end
end
context 'when created with a branch id' do
let(:attributes) { {'branch_id' => branch.id, 'name' => 'Contact Name'} }
it 'creates a contact record and associates it with the branch' do
expect(Contact.count).to eq(0)
post :create, params: {contact: attributes}
expect(Contact.count).to eq(1)
contact = Contact.first
expect(contact.branch).to eq(branch)
end
end
end
end