代码之家  ›  专栏  ›  技术社区  ›  oneWorkingHeadphone

检查上次保存的忽略对象的项目。新

  •  0
  • oneWorkingHeadphone  · 技术社区  · 6 年前

    我有一个标准Rails视图,在 new.html.erb

    <% if @user.items.last.issue_date + 2.years > Date.today %>
      ...show warning...
    <% end %>
    

    但这会阻塞,因为最后一条记录与用户关联,即在窗体的控制器中创建的空对象

    def new
      @user = User.find(params[:user_id])
      @item = @user.items.new
    end
    

    看来我可以通过

    <% if @user.items.offset(0).last.issue_date + 2.years > Date.today %>
    

    但这似乎根本不应该起作用,因为博士后医生说

    OFFSET 0 is the same as omitting the OFFSET clause.

    所以,我有两个问题:

    • 是否有更好的方法仅检查保存在数据库中的记录?
    • 为什么ActiveRecord偏移量调用行为(显然)与Postgres医生所说的有所不同?
    1 回复  |  直到 6 年前
        1
  •  2
  •   Unixmonkey    6 年前

    新的 @item 你在控制器中的存在是在 @user.items 集合,但尚未保存到数据库。

    这就是为什么要添加 .offset(0) 为你工作,因为 .where() 子句,您正在更改 条件 返回的记录中,只有从数据库返回的记录,而您的新记录不是其中之一。

    另一种过滤方法如下:

    @user.items.reject(&:new_record?).last
    

    或者这个:

    @user.items.reject { |item| item == @item }.last
    

    然而 .reject 与从数据库中提取大量数据或记录相比,性能较差。

    否则,您所拥有的功能会起作用,但我会使用一个不那么脆弱(偏移量可能会改变)且更能揭示意图的查询,如下所示:

    @user.items.
      where('issue_date < ?', 2.years.ago).
      order(issue_date: :desc).
      limit(1).
      last
    

    理想情况下,你可以用 User 模型中名为以下内容的查询方法或范围 @user.issues.expired @user.issued_less_than(2.years.ago) ,或适用于您的应用程序的任何内容。

    还有,我希望 @用户。项目 是按关系排序的,因为Postgres不总是按任何特定顺序返回项目,除非您指定一个顺序。

    has_many :items, -> { order(id: :desc) }