Ruby 객체를 해시로 변환하는 방법

7570 단어 rubyrails
속성이 Product & @name = "Table"@price = 10 개체가 있다고 가정해 보겠습니다. Rails에서 이 객체를 해시로 변환하는 가장 좋은 방법은 무엇입니까{ name: "Table", price: 10 }?

왜요?



오늘 저녁 일찍 서버에 일부 데이터를 게시하기 위해 an integration test을 쓰려고 했습니다. 내가 만들려고 했던 ActiveRecord 모델에는 많은 속성이 있어서 내params 개체가 상당히 커졌습니다.

post records_path, params: { record: { attr_one: "", attr_two: "", ..., attr_n: "" } }


하지만 테스트를 위해 FactoryBot을 사용하고 있었고 팩토리를 사용하여 쉽게 폐기 객체를 만들 수 있었습니다.

record = build(:record)


이제 이record 객체를 속성 이름을 키로, 해당 값을 해시 값으로 사용하여 해시로 변환하는 간단한 방법이 있는 경우에만 가능합니다.

이를 달성하는 몇 가지 방법이 있습니다.

as_json 메서드



as_json 메서드는 모델을 해시로 변환합니다. 여기에는 키로 이름이 있는 속성과 값으로 속성 값이 포함되어 있습니다.

user = User.find(1)
user.as_json
# => { "id" => 1, "name" => "Konata Izumi", "age" => 16 }


또한 모델 자체를 개체의 루트로 포함할 수 있습니다.

user = User.find(1)
user.as_json(root: true)
# => { "user" => { "id" => 1, "name" => "Konata Izumi", "age" => 16 } }


이 방법을 사용하면 결과 JSON 표현을 더 잘 제어할 수 있습니다. 예를 들어 :only:except 옵션을 사용하여 각각 포함하고 건너뛸 속성을 선택할 수 있습니다. 자세한 내용은 documentation 을 참조하십시오.

이 방법을 사용하여 코드를 다음과 같이 단순화했습니다.

post records_path, params: build(:record).as_json(root: true)


속성 방법



ActiveRecord#attributes 은 사용할 수 있는 또 다른 방법입니다. 활성 레코드가 있는 경우 attributes는 이름이 키이고 속성 값이 값인 모든 속성의 해시를 반환합니다.

class Person < ActiveRecord::Base
end

person = Person.create(name: 'Francesco', age: 22)
person.attributes
# => {"id"=>3, "created_at"=>Sun, 21 Oct 2012 04:53:04, "updated_at"=>Sun, 21 Oct 2012 04:53:04, "name"=>"Francesco", "age"=>22}

attributes 메서드는 모든 키가 문자열인 해시를 반환합니다. 원하는 경우 적절하게 명명된 symbolize_keys 메서드 또는 해당 별칭to_options을 사용하여 해시를 쉽게 기호화할 수 있습니다.

hash = { 'name' => 'Rob', 'age' => '28' }

hash.symbolize_keys
# => {:name=>"Rob", :age=>"28"}


이러한 방법을 사용하여 코드를 다음과 같이 리팩토링했습니다.

post records_path, params: { record: build(:record).attributes.to_options }


루비 방식



일반 Ruby 솔루션을 찾고 있다면 메타프로그래밍을 사용하여 이를 수행할 수 있습니다. 이를 위해서는 두 가지 방법이 필요합니다.
  • instance_variables 객체의 인스턴스 변수 배열을 반환합니다.
  • instance_variable_get는 변수 이름이 지정된 인스턴스 변수의 값을 반환합니다.

  • 이를 통해 다음과 같이 할 수 있습니다.

    hash = Hash.new
    record.instance_variables.each do |v| 
      hash[v.to_s.delete("@")] = record.instance_variable_get(v) 
    end
    


    어떻게 생각해?

    좋은 웹페이지 즐겨찾기