我有一个标准的 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 %>
但这似乎根本不应该起作用,因为 Postgres 文档说
OFFSET0 与省略 OFFSET 子句相同。
所以,我有两个问题:
- 有没有更好的方法来仅检查已保存在数据库中的记录?
- 为什么 ActiveRecord 偏移调用行为(显然(与 Postgres 文档所说的不同?
您在控制器中引入的新@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.issues.expired
或@user.issued_less_than(2.years.ago)
的User
查询方法或范围中,或任何适用于你的应用的内容。
另外,我希望@user.items
关系是有序的,因为 Postgres 并不总是以任何特定顺序返回项目,除非您指定一个。
has_many :items, -> { order(id: :desc) }