我正试图在RubyonRails上创建一个作业板。我正在使用设备处理帐户,我有一个员工(设备用户)和公司模型。
在这个挑战中,当有人以员工身份创建帐户时,我必须检查公司域是否已经存在(该域是从员工电子邮件中提取的),如果不存在,则必须将员工重定向到用于注册公司的页面。此外,第一位员工成为公司的行政人员。
问题是,如何做好两者之间的关系?如果我使用彼此之间的belongs_to关系,那么没有公司就不可能创建员工,反之亦然。如果我不这样做,以后就没有办法访问一些id来建立正确的关系。更糟糕的是,稍后我需要为招聘广告创建一个JobAd模型,它应该属于公司和员工。那么,有没有任何方法可以在没有";没有公司的雇员,反之亦然";问题
这是我的方案。rb
ActiveRecord::Schema.define(version: 2021_02_23_032327) do
create_table "applicants", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["email"], name: "index_applicants_on_email", unique: true
t.index ["reset_password_token"], name: "index_applicants_on_reset_password_token", unique: true
end
create_table "companies", force: :cascade do |t|
t.string "name"
t.string "logo"
t.string "address"
t.string "cnpj"
t.string "site"
t.string "social_media"
t.string "domain"
t.integer "employee_id", null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["employee_id"], name: "index_companies_on_employee_id"
end
create_table "companies_employees", id: false, force: :cascade do |t|
t.integer "employee_id", null: false
t.integer "company_id", null: false
t.index ["company_id", "employee_id"], name: "index_companies_employees_on_company_id_and_employee_id"
t.index ["employee_id", "company_id"], name: "index_companies_employees_on_employee_id_and_company_id"
end
create_table "employees", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["email"], name: "index_employees_on_email", unique: true
t.index ["reset_password_token"], name: "index_employees_on_reset_password_token", unique: true
end
create_table "job_ads", force: :cascade do |t|
t.string "title"
t.text "description"
t.integer "salary_range"
t.integer "level"
t.date "mandatory_requirements"
t.integer "total_vacancy"
t.integer "company_id", null: false
t.integer "employee_id", null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["company_id"], name: "index_job_ads_on_company_id"
t.index ["employee_id"], name: "index_job_ads_on_employee_id"
end
add_foreign_key "companies", "employees"
add_foreign_key "job_ads", "companies"
add_foreign_key "job_ads", "employees"
end
我现在正在尝试:
员工的设备注册_controller.rb
class Employees::RegistrationsController < Devise::RegistrationsController
def after_sign_up_path_for(resource)
domain = resource.email.split('@').last
if domain_is_free?(domain)
@employee.save
redirect_to new_company_path
flash[:notice] = "Não identificamos o domínio #{domain}, por favor registre-o"
else
redirect_to root_path
end
end
def create
@employee = Employee.new(employee_params)
if @employee.save
sign_in(@employee)
after_sign_up_path_for(@employee)
else
render :new
end
end
protected
def domain_is_free?(employee_mail)
!Company.exists?(['domain LIKE ?', "%#{employee_mail.split('@').last}%"])
end
def employee_params
params.require(:employee)
.permit(:email, :password, :password_confirmation)
end
company.rb
class Company < ApplicationRecord
belongs_to :employee
has_many :employees
has_many :job_ads
end
employee.rb
class Employee < ApplicationRecord
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
belongs_to :company, optional: true
end
rsspec测试
require 'rails_helper'
feature 'employee creates an account' do
scenario 'and is the first to register a domain' do
visit root_path
click_on 'Employee registration'
within('form') do
fill_in 'Email', with: 'roger@jobs.com'
fill_in 'Password', with: '123456'
fill_in 'Password confirmation', with: '123456'
click_on 'Sign up'
end
expect(current_path).to eq new_company_path
expect(page).to have_content 'There is no company named jobs, please register it'
expect(page).to have_content 'Register Company'
end
最后是错误信息
Failure/Error:
params.require(:company)
.permit(:name, :logo, :address, :cnpj, :site, :social_media, :domain).merge(employee_id: current_employee.id)
ActionController::ParameterMissing:
param is missing or the value is empty: company
Did you mean? controller
action
我想您对这里的关联感到困惑,请尝试从company.rb
文件中删除belongs_to :employee
。
所以belongs_to的意思是,模型A的一个实例属于模型B的一个例子。这意味着没有B的实例,A的实例就不可能存在(例如,没有Author,Book就不可能生存)。查看此链接了解更多信息!
另外,当您希望员工成为公司的管理员时,请在employee.rb中添加admin字段作为布尔值。
我不确定我是否理解了所有的东西。。。
- 定义
belongs_to
关系时,必须为此表提供外键。在employee.rb
中,您编写ruby belongs_to :company, optional: true
,但不将company_id
字段添加到employees
表中
create_table "employees", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.index ["email"], name: "index_employees_on_email", unique: true
t.index ["reset_password_token"], name: "index_employees_on_reset_password_token", unique: true
end
class Employee < ApplicationRecord
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
belongs_to :company, optional: true
end
也许你只需要这个has_one
。
- 如果您只使用
@employee.create_company(company_params)
在这种情况下,您不必通过带有params的employee_id
。但同样,您应该将外键添加到Employees表中,或者替换为Employee
模型中的has_one :company
。
- 您可以尝试同时创建
employee
和company
将accepts_nested_attributes_for :company
添加到Employee
模型中,在控制器中您可以调用类似的东西:
def create
...
@employee.create(employee_params)
...
end
def employee_params
params.require(:employee)
.permit(:email, :password, :password_confirmation, company_attributes: [:name, :logo, :address, :cnpj, :site, :social_media, :domain])
end
但是,只有将company_id
字段添加到Employee表中,它才会起作用。不管怎样,你也可以这样做,反之亦然。