Q:親クラスに関するネストされたクラスの情報を共有する方法
class Post
MODEL = self
extend PostMod
has_many :comments, :class_name => 'Post::Comment'
class Comment
include CommentMod
belongs_to :model, :class_name => "Post"
def method_in_comment
puts MODEL
end
end
class Another
end
end
module CommentMod
def method_in_mod1
puts self.class::MODEL
end
def method_in_mod2
puts MODEL
end
end
module PostMod
def method_in_mod1
puts self::Comment
end
end
b = Post::Comment.new
b.method_in_comment # Post
b.method_in_mod1 # uninitialized constant Post::Comment::MODEL (NameError)
b.method_in_mod2 # uninitialized constant CommentMod::MODEL (NameError)
この例(実際のシステムははるかに複雑です)のこのような設計の理由は、「モジュールを含める」だけで任意のモデルにコメントを追加することです。これにより、コントローラー、ビュー、モデルメソッドが追加されます
コメントの動作は、すべてのモデルで同様です。ただし、何かを調整する必要がある場合、モデルはCommentクラスのメソッドをオーバーライドできます。
これのトリッキーな部分は、モジュールがトップクラス(Post)と同じレベルのクラス(Comment and Another)について何も知らないということですが、それらのモジュールでいくつかのクラスメソッドを呼び出す必要があります。
現在、class.name解析を使用して、最上位クラスのクラス名を取得していますが、別の方法があるはずです。
デザインの変更など、どんな提案でも大歓迎です。
アップデート
投稿とコメントはほんの一例です。私のプロジェクトにはこのモデルはありません。
アンダースコアなし(またはCamelCase)からネストされたクラス(ArticleTranslationからArticle :: Translation)に移行しています。それは私にはもっとはっきりしているように見えます。以前のバージョンでは、モデル名を使用してクラスのクラスメソッドを呼び出していました(ModelTranslationなど)。これで、libモジュールをリファクタリングした後、model_nameを知る必要がなくなりました。
しかし、私は罠に陥りました。ルビーでは、次のようなクラスを再開できます。
class Post < ActiveRecord::Base
end
class Post::Comment < ActiveRecord::Base
belongs_to :language
end
class Post::Comment::Another1 < ActiveRecord::Base
end
class Post::Comment::Another2 < ActiveRecord::Base
end
class Language < ActiveRecord::Base
has_many :post_comments, :class_name => "Post::Comment"
end
そして私は問題を抱えています:サーバーの起動直後にページがロードされた場合-すべてOKですが、そのページへの次の呼び出しはエラーをスローします:そのような関連付けはありません。含まれているモジュールメソッドの呼び出し-メソッドエラーはありません。railsがPost::Comentに対して間違ったファイルをロードすると思いますが、最悪の場合、このエラーをデバッグできません...しかし、これは別の質問です。
UPDATE2
2番目の問題は解決しました。問題はヘルパークラスにありました。