簡體   English   中英

如何在 Rails 中建立員工-公司關系?

[英]How to make a Employee-Company relation in Rails?

我正在嘗試在 Ruby on Rails 上創建一個工作委員會。 我正在使用 devise 來處理帳戶,並且我有一個 Employee(設備用戶)和 Company 模型。

在這個挑戰中,當有人以員工身份創建帳戶時,我必須檢查公司域是否已經存在(該域是從員工電子郵件中提取的),如果不存在,則必須將員工重定向到注冊頁面公司。 此外,這名員工成為公司的管理員。

問題是,如何正確處理它們之間的關系? 如果我彼此之間使用 belongs_to 關系,則不可能在沒有公司的情況下創建員工,反之亦然。 如果我不這樣做,以后就無法訪問某些 ID 來建立正確的關系。 更糟糕的是,稍后我需要為招聘廣告創建一個 JobAd model,它應該屬於公司和員工。 那么,有沒有什么辦法可以在沒有“沒有公司的員工,反之亦然”的情況下實現這一點呢?

這是我的 schema.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

我現在正在嘗試的是:

員工設備的 registration_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

公司.rb

class Company < ApplicationRecord
    belongs_to :employee
    has_many :employees
    has_many :job_ads    
end

雇員.rb

class Employee < ApplicationRecord
  
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable
  belongs_to :company, optional: true                  
        
end

rspec測試

    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 的意思是 model A 的一個實例屬於 model B 的一個實例。這意味着 A 的實例不能沒有 B 的實例存在(例如 Book 不能沒有作者)。 查看此鏈接了解更多!

另外,如果您希望員工成為公司的管理員,請在 employee.rb 中添加 admin 字段為 boolean。

我不確定我是否理解了所有的事情......

  1. 當您定義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來代替。

  1. 如果你只是會使用怎么辦
@employee.create_company(company_params)

在這種情況下,您不必將employee_id與參數一起傳遞。 但是同樣,您應該將外鍵添加到 Employees 表或替換為Employee model 中的has_one:company

  1. 您可以嘗試同時創建employeecompany

accepts_nested_attributes_for:company添加到Employee model,在 controller 中你可以這樣調用:

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 表時才會起作用。 無論如何,你可以做同樣的反之亦然。

暫無
暫無

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

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