首页 > 解决方案 > 在创建时过滤 - rails

问题描述

我正在尝试检查新提交是否与现有提交的某些方面相匹配,如果是,则阻止它被创建。


if ( !Book.exists?(author: @book.author) and 
!Book.exists?(publisher: @book.publisher) ) 
or 
( !Book.exists?(name: @book.name) and 
!Book.exists?(genre: @book.genre) )

...create

问题在于,如果类型和出版商与现有记录相匹配,则不会创建该书。这显然不是我对这些运营商的打算。我试过 && 和 || 并且还将它们与 and和 or混合,知道 && 和 || 取得优先权。我还尝试将第二个逻辑放入 elsif。没用。我会很感激任何帮助。

更新:

我现在在模型中有这个代码。if @book.save我在控制器中删除了。当我保存时,页面什么都不做,但按钮在点击时保持冻结。


validate :existing_book, on: :create
# also tried before_create :existing_book

def existing_book

    existing_book = Book.find_by(author: self.author, publisher: self.publisher)

    existing_book ||= Book.find_by(name: self.name, genre: self.genre)

    if existing_book.nil?
      self.save
      redirect_to book_url(self)
    else
      throw(:abort)
      redirect_to new_book_url(self)
      errors.add("matching record exists")
    end
end

在 Rails 5+ 中阅读之后,我添加了 throw(:abort),返回 false 不会中止进程(我尝试它时没有中止)。

错误信息:No template found for BooksController#create, rendering head :no_content。所以我猜@book.save 应该在控制器中?但是before_create 仍然保存

- 更新:

我在控制器中重新添加了 .save:

    if @book.save
      redirect_to book_url(@book)
    else 
      redirect_to new_book_url(@book), alert: "Please try again."
    end

该模型:


  before_create :existing_book

  # validate :existing_book, on: :create

  def existing_book

    existing_book = Book.find_by(author: self.author, publisher: self.publisher)

    existing_book ||= Book.find_by(name: self.name, genre: self.genre)

    if existing_book != nil
      return false
    end

  end

记录仍然被创建。当 before_save 而不是 before_create 时相同。

标签: ruby-on-railsruby

解决方案


为您的模型添加before_create过滤器。假设您命名它check_existing_records

before_create :check_existing_records # add this line to the top of your model

您想在方法主体内添加代码,如果检测到不应保存新实例,该代码将返回 false。就像是:

def check_existing_records
  existing_book = Book.find_by(author: self.author, publisher: self.publisher)
  # in case no book with same author and publisher was found, check for book
  # with same name and same genre.
  existing_book ||= Book.find_by(name: self.name, genre: self.genre)
  # returns false if there is an existing record which matches these conditions
  # and stops persistence of record in the database
  existing_book.nil?
end

推荐阅读