Rails 모듈에서 mattr_accessor는 무엇입니까?


107

Rails 문서에서 이것을 실제로 찾을 수는 없지만 'mattr_accessor' 는 일반 Ruby 클래스의 'attr_accessor' (getter & setter)에 대한 모듈 결과 인 것 같습니다 .

예 : 수업에서

class User
  attr_accessor :name

  def set_fullname
    @name = "#{self.first_name} #{self.last_name}"
  end
end

예 : 모듈에서

module Authentication
  mattr_accessor :current_user

  def login
    @current_user = session[:user_id] || nil
  end
end

이 도우미 메서드는 ActiveSupport에서 제공합니다 .

답변:


181

Rails는 mattr_accessor(Module 접근 자) 및 cattr_accessor(뿐만 아니라 _ reader/ _writer버전) 으로 Ruby를 확장 합니다. Ruby attr_accessor인스턴스cattr/mattr_accessor대한 getter / setter 메서드를 생성하므로 클래스 또는 모듈 수준 에서 getter / setter 메서드를 제공 합니다. 그러므로:

module Config
  mattr_accessor :hostname
  mattr_accessor :admin_email
end

줄임말 :

module Config
  def self.hostname
    @hostname
  end
  def self.hostname=(hostname)
    @hostname = hostname
  end
  def self.admin_email
    @admin_email
  end
  def self.admin_email=(admin_email)
    @admin_email = admin_email
  end
end

두 버전 모두 다음과 같이 모듈 수준 변수에 액세스 할 수 있습니다.

>> Config.hostname = "example.com"
>> Config.admin_email = "admin@example.com"
>> Config.hostname # => "example.com"
>> Config.admin_email # => "admin@example.com"

1
귀하의 예제에서 mattr_accessor클래스 인스턴스 변수 ( @variables)의 약자 라고 설명 하지만 소스 코드는 실제로 클래스 변수를 설정 / 읽고 있음을 보여줍니다. 이 차이점을 설명해 주시겠습니까?
sandre89

38

여기에 대한 소스가 있습니다. cattr_accessor

여기에 대한 소스가 있습니다. mattr_accessor

보시다시피 그들은 거의 동일합니다.

두 가지 버전이있는 이유는 무엇입니까? 때로는 cattr_accessor모듈 을 작성 하여 Avdi 언급과 같은 구성 정보에 사용할 수 있습니다 .
그러나 cattr_accessor모듈에서는 작동하지 않으므로 모듈에서도 작동하도록 코드를 다소 복사했습니다.

또한 어떤 클래스가 모듈을 포함 할 때마다 해당 클래스 메서드와 모든 인스턴스 메서드를 가져 오도록 모듈에 클래스 메서드를 작성하려고 할 수도 있습니다. mattr_accessor또한 이것을 할 수 있습니다.

그러나 두 번째 시나리오에서는 동작이 매우 이상합니다. 다음 코드를 관찰하십시오. 특히 @@mattr_in_module비트에 유의하십시오.

module MyModule
  mattr_accessor :mattr_in_module
end

class MyClass
  include MyModule
  def self.get_mattr; @@mattr_in_module; end # directly access the class variable
end

MyModule.mattr_in_module = 'foo' # set it on the module
=> "foo"

MyClass.get_mattr # get it out of the class
=> "foo"

class SecondClass
  include MyModule
  def self.get_mattr; @@mattr_in_module; end # again directly access the class variable in a different class
end

SecondClass.get_mattr # get it out of the OTHER class
=> "foo"

이것은 default_url_options (mattr_accessor)를 직접 설정할 때 저를 꽤 어렵게 물었습니다. 일단 클래스는 그것들을 한 가지 방식으로 설정하고 다른 클래스는 그것들을 다른 방식으로 설정하여 잘못된 링크를 생성합니다.
Eric Davis

최신 버전의 Rails cattr_*는 이제 mattr_*. cattr_accessor출처
ouranos
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.