如果Ruby on Rails中已经存在记录,则提供选项

时间:2018-11-16 18:47:30

标签: ruby-on-rails ruby sqlite ruby-on-rails-5

我正在创建产品数据库,并希望检查何时创建了新产品(如果该产品已经存在)。

99%的情况下,产品应该具有唯一的产品代码,但是有时当修订版本带有相同的产品代码时,情况并非如此。

我想拥有它,以便数据库检查产品代码是否已经存在。如果是这样,则用户可以继续创建产品,转到已经存在的产品,或者取消。

我正在尝试在控制器中实现此功能,但似乎无法获取存在的语法?方法正确。有人可以指出我要去哪里了吗?

def create
    @product = Product.new(product_params)

    if Product.product_code.exists?(@product.product_code)
        render 'new'
        flash[:error] = "This product already exists."

    elsif @product.save
        redirect_to @product
    else
        render 'new'
    end

end

2 个答案:

答案 0 :(得分:0)

您应该注意,您在控制器中执行的操作或向模型添加标准唯一性验证将根本不允许创建重复的产品。

这只会继续将用户发送回表单:

def create
  @product = Product.new(product_params)
  if Product.exists?(product_code: @product.product_code)
    render 'new'
    flash[:error] = "This product already exists."
  elsif @product.save
    redirect_to @product
  else
    render 'new'
  end
end

如果只想警告用户一次,则可以在模型上附加virtual attribute并将其用作验证的条件:

class Product < ApplicationRecord
  attribute :dup_warning, :boolean, default: true
  validate :lax_product_code_uniquenes

  def lax_product_code_uniqueness
    if new_record? && !dup_warning && Product.exists(product_code: self.product_code)
      errors.add(:product_code, 'is not unique - are you sure?')
      self.dup_warning = true
    end
  end
end

然后将虚拟属性添加到表单:

<%= form_with(model: @product) do |f| %>
  ...
  <%= f.hidden_input(:dup_warning) %>
  ...
<% end %>

除了将dup_warning添加到参数白名单之外,您不需要在控制器中做任何事情。

def create
  @product = Product.new(product_params)
  if @product.save
    redirect_to @product
  else
    render 'new'
  end
end

def product_params
  params.require(:product)
        .permit(:foo, :bar, :product_code, :dup_warning)
end

答案 1 :(得分:-1)

您可能应该使用if Product.product_code.exists?(@product.product_code)代替if @product.product_code.present?

UPD:谢谢大家,在下面评论。

正确使用exists?Product.where(product_code: @product.product_code).exists?