1

「has_many through」関係を置き換えるために、Redis を Rails アプリに統合しようとしています。アプリ全体でコードを変更する必要がないように、シームレスに行いたいと思います。私の考えは、いくつかのクラス属性 (たとえば、Speaker クラスのフォロワー属性) のさまざまなメソッドをオーバーライドして、それらを使用するときにカスタム動作を作成できるようにすることです。

s = Speaker.new
s.followers # calls custom getter and returns [User1, User2]
s.followers << User.create
s.followers # calls custom getter and returns [User1, User2, User3]

これは、 Ruby でインスタンス変数配列の演算子をオーバーライドすることに触発された私のアイデアです。

class Speaker < ActiveRecord::Base  
  attr_accessor :followers

  def initialize
    super
    @followers = []
    class << @followers
      def <<(u)
        puts "setter #{u.id}" 
        $redis.set "speaker#{self.id}followers", u.id
        super(u.id)
      end
    end
  end

  def followers
    puts "getter"
    user_ids = $redis.get "speaker#{self.id}followers"
    User.find_all user_ids
  end

end

問題は、フォロワーゲッターの実装が「def <<(val)」の実装をオーバーライドすることです。

ゲッター「def follower」が定義されていない場合:

s.followers
# []
s.followers << User.create 
# "setter 1"
# [1]
s.followers
# [1]
s.followers << User.create 
# "setter 2"
# [1, 2]
s.followers
# [1, 2]

ゲッター「def attendees」が定義されている場合:

s.followers << User.create
# ["My", "Custom", "Array", User1]
s.followers
# ["My", "Custom", "Array"]
s.followers << User.create
# ["My", "Custom", "Array", User2]
s.followers
# ["My", "Custom", "Array"]

ゲッターとセッター「<<」を連携させるにはどうすればよいですか?

4

2 に答える 2

0

ここでの問題は、ゲッターが新しい配列を返すことです。配列のシングルトン クラスを変更します@followersが、それは getter で使用されていません。

def followers
  puts 'getter'
  ['a','new','array']
end

カスタムゲッターが必要な場合は、ゲッターが @followers を返すことを確認する必要があります (基になる参照を変更せずに)、または配列を再装飾する必要があります。

ただし、AlexWayne が提案したのは、これを行う適切な方法です。redis の詳細を処理するプロキシ オブジェクトを返します。

class FollowersList < SimpleDelegator
  def initialize(assoc)
    @assoc = assoc
    super(_followers)
  end

  def _reload
    __setobj__ _followers
    self
  end

  def _followers
    user_ids = $redis.get key
    User.find_all user_ids
  end

  def _key
    "speaker#{@assoc.id}followers"
  end

  # implement your overrides. The _reload method is to force the list to sync
  # with redis again, there are other ways to do this that wouldn't do the query
  # again
  def <<(val)
    $redis.lpush key, val.id
    _reload
  end

  #etc
end
于 2013-02-07T22:24:46.200 に答える
0
def followers<<(val)

それはうまくいきません。その理由は次のとおりです。

foo.followers << "abc"
# is actually 2 methods!
foo.followers().<<("abc")

そのため、オーバーライドされたメソッド#followersを持つクラスのオブジェクトを返す必要があります。#<<


Rails の関連付けが関連付けプロキシ オブジェクトを返すのと同じように。

# Book has_many Pages
book.pages # an assoc proxy
book.pages << Page.new # calls #<< on the assoc proxy

Book#pages<<存在しません。 Book#pagesのインスタンス (または類似のもの) を返し、インスタンス メソッドActiveRecord::HasManyAssociationProxyを実装します。#<<

于 2013-02-07T22:00:17.710 に答える