1

Ruby on Rails 3.2.2 と Squeel gem を使用しています。次のステートメントがあり、 Mixin モジュールmy_squeel_queryでメソッドをリファクタリングしようとしています(多くのモデルで使用されているため)。

# Note: 'article_comment_associations' and 'model_as_like_article_comment_associations'
# refer to database table names.

class Article < ActiveRecord::Base
  def my_squeel_query
    commenters.
      .where{
        article_comment_associations.article_id.eq(my{self.id}) & ...
      }
  end
end

class ModelAsLikeArticle < ActiveRecord::Base
  def my_squeel_query
    commenters.
      .where{
        model_as_like_article_comment_associations.article_id.eq(my{self.id}) & ...
      }
  end
end

私の問題は、Mixin モジュールで動的な名前を生成してステートメントをリファクタリングできないことです。つまり、次のようなものを使用して、関連する名前を動的に生成できます。article_comment_associationsmodel_as_like_article_comment_associationsString"#{self.class.to_s.singularize}_comment_associations"

class Article < ActiveRecord::Base
  include MyModule
end

class ModelAsLikeArticle < ActiveRecord::Base
  include MyModule
end

module MyModule
  def my_squeel_query
    commenters.
      .where{
        # Note: This code doesn't work. It is just an sample.
        "#{self.class.to_s.singularize}_comment_associations".article_id.eq(my{self.id}) & ...
      }
  end
end

しかし、私の場合ではないので、名前を「構築」しmy_squeel_queryてモデル間で「共有」することはできません。

Squeel gem に関連する関連付け名を動的に生成するにはどうすればよいですか? 別の方法でリファクタリングを検討する必要がありますか? 何についてアドバイスしますか?

4

3 に答える 3

1

メソッドを動的に生成する場合は、これを行うことができます。このModule.included方法は、この目的のために提供されています。

module ModuleAsLikeArticle
  def self.included(base)
    base.send(:define_method, "#{base.to_s.singularize}_comment_associations") do
      # ...
    end
  end
end

これは、モジュールがでインポートされたときにトリガーされ、includeそのために特別に調整されたメソッドを作成できます。

注意としてbase.name.underscore.singularize、より読みやすいメソッド名に使用することをお勧めします。慣例により、メソッド名には大文字を使用しないでください。特に最初の文字としては使用しないでください。

ただし、従来のRailsタイプのアプリケーションは異なるアプローチを使用しますが、代わりに、これらをオンデマンドで作成するために使用できるクラスメソッドを定義します。

module ModuleAsLikeArticle
  def has_comments
    base.send(:define_method, "#{base.to_s.singularize}_comment_associations") do
      # ...
    end
  end
end

これは次のように使用されます。

class ModelAsLikeArticle < ActiveRecord::Base
  extend MyModule

  has_comments
end

メソッドは呼び出されるまで作成されないため、その機能を必要とするすべてのクラスに適切な呼び出しをhas_comments安全に拡張して挿入できます。ActiveRecord::Base

于 2012-09-26T16:39:10.347 に答える
1

DSL は instance_evaled であるため、実際には次のように言えます。

def my_squeel_query
  base = self
  commenters.
    .where{
      # Note: This code does work. Because it's awesome.
      __send__("#{base.class.to_s.singularize}_comment_associations").
        article_id.eq(my{self.id})
    }
end
于 2012-09-26T23:13:48.460 に答える
0

ページにあるように、Rails クラス (http://api.rubyonrails.org/classes/ActiveRecord/Reflection/ClassMethods.html) で必要なものが見つかると思いますReflection。これにより、ActiveRecord クラスの関連付けについて問い合わせることができます。および集計。

于 2012-09-26T16:09:34.630 に答える