2013-06-15 9 views
6

私はPost belongs_to :user削除されたユーザの投稿を保持したいアプリケーションです。これにより、作成者が削除された投稿を表示するときにビューにエラーが発生する可能性があります。私はこれをやろうとしました:RailsでNullObjectパターンを実装する

class Post < ActiveRecord::Base 
    belongs_to :author, class_name: 'User', foreign_key: 'user_id' 

    def author 
    author || NullUser.new 
    super 
    end 
end 

これは「スタックレベルから深い」エラーを引き起こします。どうして?私はこれをすることができました:

class Post < ActiveRecord::Base 
    belongs_to :user 

    def author 
    user || NullUser.new 
    end 

    def author=(user) 
    self.user = user 
    end 
end 

しかし、私の団体にこのように混乱させるのは正しいとは思われません。これについては何が最善の方法ですか?

+3

追記:NullObjectsに関連し、ちょうど出てきた、[ノーティー](https://github.com/avdi/naught)によってAvdi Grimm –

答えて

13

あなたがauthorメソッドを定義している、ライン1では

1. def author 
2. author || NullUser.new 
3. super 
4. end 

、あなたの質問に答えるために。次に、2行目で、再びその作成者メソッドを呼び出します。これが起こり続けると、スタックレベルが深すぎるというエラーが発生します。これを行う適切な方法は、

def author 
    super || NullUser.new 
end 

です。したがって、再度authorメソッドを呼び出してはいけません。スーパークラスを呼び出すか、NullUserを返すだけです。あなたがsuperを呼び出しているとき場合は、あなたがnilエラーを取得し、その後、追加のゼロチェックを追加します。

def author 
    (super || NullUser.new) rescue NullUser.new 
end 

あなたが心配する必要はありませんので、NullUser.newを返すそしてすべてのエラーをキャッチしますレスキュー声明スーパーエラーについても同様に投げます。

EDIT:

スーパー立派に見える例外をスロー処理する別の方法:

def author 
    (super rescue nil) || NullUser.new 
end 
2

削除したユーザーの投稿を保持したい場合は、本当に「削除」しない方が良いでしょう。

「ソフト削除」です。ブール値の列に「削除済み」または「非アクティブ」を追加するだけです。

したがって、ユーザーを削除するときに、彼が投稿を持っているかどうかを確認します。何もなければ、彼を削除してください。持っている場合、ソフト削除します。

このようにすれば、はるかにシンプルでクリーンになります。

もう1つの方法は、投稿を「盗む」ことです。ユーザーを削除するときは、すべての投稿を特別なユーザーアカウントで移動してから削除します。

いずれにしても、関連付けを解除しません。

関連する問題