您如何仅引用活动记录关联中的持久记录 [英] How do you reference only the persisted records in an active record association

查看:15
本文介绍了您如何仅引用活动记录关联中的持久记录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在许多控制器的编辑方法中,您初始化一个新对象并编辑现有对象

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆