ActiveModel: 모델 모듈의 initialize 방법은 무엇입니까

10197 단어 RailsRubytech

개시하다


ActiveModel:include에 모델 추가
실례를 생성할 때 실례 변수를 간단하게 실례 변수에 대입하는 것이 아니라 설정 방법을 통해 대입하는 것을 알 수 있다.
# initializeメソッドを作成する場合
class User
  attr_reader :name

  def initialize(attributes = {})
    @name = attributes[:name]
  end

  def name=(name)
    @name = "#{name}君"
  end
end

User.new(name: "俺")
=> #<User:0x00007f8c42d26b28 @name="俺">
# ActiveModel::Modelをincludeする場合
class User
  include ActiveModel::Model
  attr_reader :name

  def name=(name)
    @name = "#{name}君で〜す"
  end
end

User.new(name: "俺")
=> #<User:0x00007f8c52d93150 @name="俺君で〜す">
그럼 이번에는ActiveModel::모델include에서 호출된 initialize 방법을 조사합니다.

ActiveModel::Model


# rails/activemodel/lib/active_model/model.rb
module ActiveModel
  ..(省略)..
  module Model
		include ActiveModel::AttributeAssignment
		..(省略)..
    def initialize(attributes = {})
      assign_attributes(attributes) if attributes
      super()
    end
  end
end
rails/model.rb
initialize 방법,assignattributes라는 방법이 호출되었습니다.이 방법은 Active Model::Attribute Assignment 모듈에 포함되어 있습니다.

assign_attributes 방법


# rails/activemodel/lib/active_model/attribute_assignment.rb
module ActiveModel
  module AttributeAssignment
    include ActiveModel::ForbiddenAttributesProtection

    def assign_attributes(new_attributes)
          # new_attributesがeach_pairメソッドを持たなければ(= hashでなければ)エラー
      unless new_attributes.respond_to?(:each_pair)
        raise ArgumentError, "When assigning attributes, you must pass a hash as an argument, #{new_attributes.class} passed."
      end
      return if new_attributes.empty?

      # sanitize_for_mass_assignmentはマスアサインメントの際の許可に関するメソッドで、
            # インスタンス生成時にhashをそのまま入れる場合は関係ないので今回は省略します	
      _assign_attributes(sanitize_for_mass_assignment(new_attributes))
    end

    alias attributes= assign_attributes

    private
      def _assign_attributes(attributes)
        attributes.each do |k, v|
          _assign_attribute(k, v)
        end
      end

      def _assign_attribute(k, v)
        setter = :"#{k}="
        if respond_to?(setter)
          public_send(setter, v)
        else
          raise UnknownAttributeError.new(self, k.to_s)
        end
      end
  end
end
rails/attribute_assignment.rb
assign_attributes 방법 중assign_이른바 attributes의 privete 방법이 호출되었다는 것을 알 수 있다assign_attribute방법public_send 메서드에서 보듯이setter방법이라고 부른다.
# public_methodでメソッドを呼び出す例
class Child
  def greeting(name)
    p "おはようございます、#{name}さん!"
  end
end

Child.new.public_send("greeting", "太郎")
=> "おはようございます、太郎さん!"
에서 알 수 있듯이 ActiveModel:::Model은include와 initialize 방법에서 Senter 방법이라고 불린다.
include가 아니라 코드를 직접 가지고 있으면 다음과 같이 됩니다(오류 처리 등 생략)
class Person
  attr_reader :name

	def initialize(attributes = {})
    assign_attributes(attributes) if attributes
  end

  def name=(name)
    @name = "#{name}君"
  end

  private

  def assign_attributes(attributes)
    _assign_attributes(attributes)
  end

  def _assign_attributes(attributes)
    attributes.each do |k, v|
      _assign_attribute(k, v)
    end
  end

  def _assign_attribute(k, v)
    setter = :"#{k}="
    if respond_to?(setter)
      public_send(setter, v)
    else
      raise UnknownAttributeError.new(self, k.to_s)
    end
  end
end

Person.new(name: "太郎")
=> #<Person:0x00007f8c52b22a60 @name="太郎君">

좋은 웹페이지 즐겨찾기