创建员工时,他会获得一个头衔。如果标题是唯一的,则记录会正常保存。如果标题不是唯一的,我想找到现有的标题,然后使用它。我无法弄清楚如何在创建动作中执行此操作。
employer.rb
class Employee < ActiveRecord::Base
belongs_to :title, :class_name => :EmployeeTitle, :foreign_key => "employee_title_id"
accepts_nested_attributes_for :title
end
employer_title.rb
class EmployerTitle < ActiveRecord::Base
has_many :employees
validates :name, presence: true, length: { maximum: 50 },
uniqueness: { case_sensitive: true }
end
new.html.erb
<%= f.simple_fields_for :title do |title| %>
<%= title.input :name, label: "Title" %>
<% end %>
employees_controller.rb
def create
if EmployeeTitle.exists?(name: employee_params[:title_attributes][:name])
# find title and use it?
else
@employee = current_user.employee.build(employee_params)
end
if @employee.save
flash[:success] = "Employee #{@employee.title.name} created."
redirect_to @employee
else
render 'new'
end
end
编辑:使用first_or_create
def create
EmployeeTitle.where(name: employee_params[:title_attributes][:name]).first_or_create do |title|
@employee = current_user.employees.build(employee_params, :title => title)
end
if @employee.save
flash[:success] = "Employee #{@employee.title.name} created."
redirect_to @employee
else
render 'new'
end
end
这使@employee超出了范围。错误:未定义的方法`save&#39;为零:NilClass。
此外,如果我这样做,无论其他员工数据是否有效,都不会创建标题?
使用私有方法
employee.rb
private
def title_attributes=(attributes)
self.title = EmployeeTitle.find_or_create_by_name(name: attributes[:name])
end
未设置该值。我得到一个&#34;不能空白&#34;验证错误。参数包括
employee: !ruby/hash:ActionController::Parameters
title: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
name: Consultant
以前没有!ruby / hash:ActiveSupport :: HashWithIndifferentAccess。
employee_params
private
def employee_params
params.require(:employee).permit(
title_attributes: [:id, :name],
)
end
答案 0 :(得分:2)
您需要做的是改变这一点:
def create
if EmployeeTitle.exists?(name: employee_params[:title_attributes][:name])
# find title and use it?
else
@employee = current_user.employee.build(employee_params)
end
if @employee.save
flash[:success] = "Employee #{@employee.title.name} created."
redirect_to @employee
else
render 'new'
end
end
用这个:
def create
@employee = current_user.employee.build(employee_params)
if @employee.save
flash[:success] = "Employee #{@employee.title.name} created."
redirect_to @employee
else
render 'new'
end
end
现在,通过将此代码放在 app / models / employee.rb 文件中来覆盖title_attributes
方法:
def title_attributes=(attributes)
self.title = EmployeeTitle.find_or_create_by_name(attributes[:name])
end
现在,每次您创建名称已存在且具有特定名称的员工时,默认情况下都会将其用于将其关联为title
。让控制器像以前一样 skinny 。
在此处详细了解find_or_create_by
方法。
但是,你的问题的标题是:Rails 4,但你已经标记了ruby-on-rails-3.2。如果您使用的是Rails 4,那么您可以使用它:
EmployeeTitle.find_or_create_by(name: attributes[:name])