简体   繁体   中英

Rails 5 generate parent record on child creation, only if not already present

I have two models, User and Company. I have used the device gem for User model creation.

class User < ApplicationRecord
  belongs_to :company
  accepts_nested_attribute_for :company
  devise :database_authenticatable, :registerable,
     :recoverable, :rememberable, :trackable, :validatable, :confirmable, :lockable
end

class Company < ApplicationRecord
  has_many :users
end

When I create users, I want to associate with them the company they work in. I have included the company_name attribute in the user creation form. What I don't want is the company table to have multiple records for the same company_name attribute.

<% form_for(@user) do |user_form| %>
  <% user_form.fields_for :company do |company_form| %>
    <%= company_form.label :company_name %>
    <%= company_form.text_field :company_name %>
  <% end %>
# other fields for user
<% end %>

I want to check if the company the user is associated with, is already present or not in the company table. Create a new record for the company only if it is not already present.

class User < ApplicationRecord
  before_save :create_or_initialize_company

  private
  def create_or_initialize_company
    Company.where("name ILIKE '%#{company_name}%'").first_or_create
  end
end

Now here, you can do couple of variations based on your requirements eg If you want exact match then .where(name: company_name) If you don't want case insensitive match then replace ILIKE with LIKE .

Hope it helps..

class UsersController < ApplicationController
  def create
    @user = User.new(user_params)
    assign_new_or_existing_company(@user)

    if @user.save
    # ...
  end

  def update
    @user = User.find(params[:id])
    @user.assign_attributes(user_params)
    assign_new_or_existing_company(@user)

    if @user.save
    # ...
  end

  private

  def assign_new_or_existing_company(user)
    user.company = Company.where(
      'company_name ILIKE ?',
      "%#{user_params[:company_attributes][:company_name]}%"
    )
    .first_or_initialize(user_params[:company_attributes])
  end

  def user_params
    params.require(:user).permit(:id, company_attributes: [:company_name])
  end
end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM