11

多くのコントローラの edit メソッドでは、新しいオブジェクトを初期化し、既存のオブジェクトを編集します

class MagazinesController < ApplicationController
   def edit
      @magazine = Magazine.find(params[:magazine_id])
      @page = Page.find(params[:id])
      @new_page = @magazine.pages.new
   end
end

ただし、ビューでは、永続化されたオブジェクトを循環させて、新しいオブジェクトを個別に扱いたいことがよくあります。

# magazines#edit
%h4 Existing pages
- @magazine.pages.each do |page|
  %p= link_to page, page.title

問題

...pages関連付けには、既存の (永続化された) ページだけでなく、 を介して作成した新しいページも含まれているということ@new_page = @magazine.pages.newです。

これに対処するのは簡単ですが、醜いです

%h4 Existing pages
- @magazine.pages.each do |page|
  - if page.persisted?
    %p= link_to page, page.title

関連付けメソッドを使用して、永続化されているページのみを選択したいと思います。

%h4 Existing pages
- @magazine.pages.persisted.each do |page|
  %p= link_to page, page.title

これを行う方法はありますか?

4

6 に答える 6

4

@ Florent2 と @CDub からの提案はどちらも適切です。ただし、@ florent2 の提案は、データベースに再度アクセスすることを意味し (そして、私がやりたくない事前設定された熱心な読み込みを破棄する可能性があります)、@CDub の提案はコードに関してはうまくいきませんでした。これが私が最終的に行ったものです:

特定の関連付けの永続化されたレコードのみを返す

class Magazine < ActiveRecord::Base
  has_many :pages do 
    def persisted
      collect{ |page| page if page.persisted? }
    end
  end
end

.persistedこれにより、Magazine に関連付けられたページの ActiveRecord リレーションを呼び出すことができます。永続化されたオブジェクトを返すプリロードされたオブジェクトを単純にフィルタリングするため、データベースに再びヒットすることはありません。

コードを再利用可能にする

このコードを定期的に再利用したいので、モジュールに引き出すことができます

module PersistedExtension
  def persisted
    select{|item| item if item.persisted?}
  end
end

次に、ラムダを使用して関連付けメソッドに含めることができます。

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
于 2013-11-08T10:46:52.633 に答える
0

Rails 4 および 5 の回答:

このコードを初期化子に入れるだけです(ディレクトリ内のファイル、config/initializers拡張子付き.rb):

module MyApp
  module ActiveRecordExtensions
    extend ActiveSupport::Concern

    class_methods do

      def persisted
        select(&:persisted?)
      end

    end
  end
end

ActiveSupport.on_load :active_record do
  include MyApp::ActiveRecordExtensions
end

persistedこれで、任意のモデルと関連付けを呼び出すことができます。

于 2016-07-23T18:34:42.280 に答える