0
module Foo
  attr_accessor :val
end

module Bar
  def bar
    val = 50
  end
end

class FooBar
  include Foo
  include Bar
end

fb = FooBar.new
puts fb.bar # 50
puts fb.val # nil

Bar 内から、Foo の「val」値を変更したいと思います。

Clearance (0.8.2 (old, I know)) で Facebook Canvas アプリを介してユーザー認証を追加したいので、これを実行しようとしています。変更したい変数はhttps://github.com/thoughtbot/clearance/blob/b8ccca00d91cb336e044b76b5c6ae1d8de9d2d8d/lib/clearance/authentication.rb#L25です。

このモジュールは ApplicationController にインクルードされ、その後、次のようなことを行う別のモジュール (FacebookAuthenticationHelper) をインクルードしています。

def authenticate_facebook
  current_user ||= facebook_user if coming_from_facebook?
end

これを行うためのより良い方法があれば、私も知りたいです。私はOAuthを使用していません。Facebookのuser_idがsigned_requestからアプリに送信したものをDBに保存しているだけです。

ありがとう!

4

1 に答える 1

1

ruby では、この形式のステートメントは、varname = value名前が付けられたローカル変数varnameがまだ存在しない場合にそれを作成します。 これは、クラスに同じ名前のセッター メソッドがあるクラス メソッド内でも当てはまります。 さらに、ローカル変数が存在する場合は、getter および setter よりも優先されます。例えば:

class Demo
    attr_accessor :foo

    def demonstrate!
        @foo = 1      #1: Set member variable foo, so we get meaningful output
        puts foo      #2: Prints 1 (this calls the getter)
        puts self.foo #3: Prints 1 (also calls the getter)

        foo = 2       #4: Creates a LOCAL variable named foo with the value 2
        puts foo      #5: Prints 2 (locals take precedence over getters)
        puts self.foo #6: Prints 1 (calls the getter - the member variable hasn't changed)

        self.foo = 3  #7: Use SELF to ensure you call a getter or setter
        puts foo      #8: Prints 2 (the local again)
        puts self.foo #9: Prints 3 (the member, which is now 3)
    end
end

このシステムの悪い点は次のとおりです。2 行目と 5 行目を見てください。 まったく同じコードが異なることを行っています。 2 行目では、ローカル変数fooがまだ存在していなかったので、ruby は「次善の策」を実行して getter を呼び出しました。しかし、5 行目では localfooが存在するため、それが優先されます。

これは言語設計が悪いと思います: setter を なしselfで呼び出すことができない場合、getter を使用しても問題ないはずです。特に、上記のようなガタガタしたコンテキスト依存のコードにつながる可能性がある場合はどうすればよいでしょうか? しかし、それは私たちが取り組まなければならないものであり、いくつかの一般的なガイドラインにつながります。

  1. 可能であれば、使用して@fooください。それが何をするかは明らかです。
  2. ゲッターまたはセッターを使用している場合はself、厳密に必要でない場合でも、常に を使用してください。これにより、何を呼び出しているかが明確になります。また、後で同じ名前のローカルを追加しても、コードの動作が異なることはありません。
  3. @1 と 2 を実行すると、aまたは a のないものはすべてselfローカル変数 (または関数呼び出しですが、おそらく名前で区別できます) であると見なすことができます。

そして、それは少し長くなりましたが、リンクするゲッター/セッター/ローカルの問題の適切なデモンストレーションを見つけることができませんでした. たぶんこれで終わりです。お役に立てば幸いです。

于 2012-09-12T19:54:38.463 に答える