您如何仅引用活动记录关联中的持久记录 [英] How do you reference only the persisted records in an active record association
问题描述
在许多控制器的编辑方法中,您初始化一个新对象并编辑现有对象
In the edit method of many controllers you initialize a new object and edit existing objects
class MagazinesController < ApplicationController
def edit
@magazine = Magazine.find(params[:magazine_id])
@page = Page.find(params[:id])
@new_page = @magazine.pages.new
end
end
但是在视图中,您通常希望循环遍历持久化对象并单独处理新对象
However in a view you will often want to cycle through the persisted objects and treat the new object separately
# magazines#edit
%h4 Existing pages
- @magazine.pages.each do |page|
%p= link_to page, page.title
问题
...是 pages
关联既包含现有(持久)页面,也包含我们通过 @new_page = @magazine.pages.new
创建的新页面.
The problem
...is that the pages
association contains both existing (persisted) pages but also the new page which we made via @new_page = @magazine.pages.new
.
这很容易处理,但它很丑
It's easy to deal with this however it's ugly
%h4 Existing pages
- @magazine.pages.each do |page|
- if page.persisted?
%p= link_to page, page.title
我想使用一些关联方法来只选择那些被持久化的页面:
I would like to use some assocition method to select only those pages which are persisted:
%h4 Existing pages
- @magazine.pages.persisted.each do |page|
%p= link_to page, page.title
有没有办法做到这一点?
Is there any way of doing this?
推荐答案
@Florent2 和@CDub 的建议都是合理的.然而,@florent2 的建议意味着再次访问数据库(并可能放弃我不想做的任何预设的急切加载),而@CDub 的建议在代码方面并没有完全奏效.这是我最终的结果:
Both the suggestions from @Florent2 and @CDub are sound. However @florent2's suggestion meant hitting the database again (and potentially ditching any preset eager loading which I didn't want to do) and @CDub's suggestion didn't quite work out in terms of code. Here is what I ended up going with:
class Magazine < ActiveRecord::Base
has_many :pages do
def persisted
collect{ |page| page if page.persisted? }
end
end
end
这允许您在与杂志关联的页面的任何 ActiveRecord 关系上调用 .persisted
.它不会再次访问数据库,因为它只是过滤预加载的对象,返回持久化的对象.
this allows you to call .persisted
on any ActiveRecord relation of pages associated with Magazine. It doesn't hit the database again as it simply filters through the pre-loaded objects returning the ones which are persisted.
因为我想定期重用这段代码,所以我可以把它拉到一个模块中
Since I want to reuse this code on a regular basis I can pull it out into a module
module PersistedExtension
def persisted
select{|item| item if item.persisted?}
end
end
然后可以使用 lambda 将其包含到关联方法中:
It can then be included into the association methods using a lambda:
class Magazine < ActiveRecord::Base
# ...
has_many :pages, -> { extending PersistedExtension }
end
我可以直观地称之为:
@magazine = Magazine.first
@magazine.pages.persisted
# => array of pages which are persisted
# the new persisted association extension works on any AR result set
@magazine.pages.order('page ASC').persisted
这篇关于您如何仅引用活动记录关联中的持久记录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!