Rails 직렬화를 사용하여 해시를 데이터베이스에 저장


135

rails 앱에서 여러 시도에 해시 매핑 ID를 저장하려고합니다. 이 새 열을 수용하기 위해 데이터베이스로 마이그레이션했습니다.

class AddMultiWrongToUser < ActiveRecord::Migration
  def self.up
    add_column :users, :multi_wrong, :string
  end

  def self.down
    remove_column :users, :multi_wrong
  end
end

내 모델에는 다음이 있습니다.

class User < ActiveRecord::Base 
 serialize :multi_wrong, Hash
end

그러나 레일 콘솔을 사용하여 다음을 수행하여이를 테스트 할 때 :

user = User.create()
user.multi_wrong = {"test"=>"123"}
user.save

출력이 거짓입니다. 무슨 일이야?


4
레코드를 저장하려고 시도한 후 user.errors에 어떤 것이 있습니까?
Martijn

1
나중에 bang 메소드 (save!)를 사용하여 예외를 발생시키고 오류 메시지를 표시 할 수 있습니다.
leishman

우수 답변은 이제 JSON 열 사용 stackoverflow.com/a/21397522/1536309을
블레어 앤더슨에게

답변:


174

열 유형이 잘못되었습니다. 문자열 대신 텍스트를 사용해야합니다. 따라서 마이그레이션은 다음과 같아야합니다.

 def self.up
   add_column :users, :multi_wrong, :text
 end

그러면 Rails가이를 YAML로 올바르게 변환하고 적절한 직렬화를 수행합니다. 문자열 필드는 크기가 제한되며 특히 작은 값만 보유합니다.


1
@BenjaminTan의 이유는 무엇입니까, 왜 'string'데이터 형식으로 해시를 저장할 수 없습니까?
Lohith MV

8
데이터베이스에서 String의 길이는 255입니다 (제 생각에는). 그러나 비교 크기의 해시를 직렬화하면 길이를 쉽게 초과 할 수 있습니다. 배열의 경우도 마찬가지입니다. 텍스트는 훨씬 더 긴 길이를 허용합니다.
Benjamin Tan Wei Hao

72

업데이트 :

정확한 구현은 데이터베이스에 따라 달라집니다 만, PostgreSQL는 지금이 jsonjsonb기본적으로 당신의 해시 / 객체 데이터를 저장하고 당신이에 허용 할 수 있습니다 열 액티브와 JSON에 대한 쿼리를 !

마이그레이션을 변경하면 완료됩니다.

class Migration0001
  def change
    add_column :users, :location_data, :json, default: {}
  end
end

실물:

자세한 내용 : rails docs && apidock

반드시 당신의 열이 있는지 확인 :text하지:string

이주:

$ rails g migration add_location_data_to_users location_data:text

만들어야합니다 :

class Migration0001
  def change
    add_column :users, :location_data, :text
  end
end

수업은 다음과 같습니다.

class User < ActiveRecord::Base
  serialize :location_data
end

가능한 조치:

b = User.new
b.location_data = [1,2,{foot: 3, bart: "noodles"}]
b.save

더 굉장해?!

postgresql hstore를 활용하십시오

class AddHstore < ActiveRecord::Migration  
  def up
    enable_extension :hstore
  end

  def down
    disable_extension :hstore
  end
end 

class Migration0001
  def change
    add_column :users, :location_data, :hstore
  end
end

hstore를 사용하면 직렬화 된 필드에서 속성을 설정할 수 있습니다

class User < ActiveRecord::Base  
  # setup hstore
  store_accessor :location_data, :city, :state
end

2
정말 대단해! 감사!
Alexander Gorg

18

Rails 4에는 Store 라는 새로운 기능이 있으므로 문제를 쉽게 해결하는 데 사용할 수 있습니다. 접근자를 정의 할 수 있으며 직렬화 된 저장소에 사용 된 데이터베이스 열을 텍스트로 선언하는 것이 좋으므로 충분한 공간이 있습니다. 원래 예 :

class User < ActiveRecord::Base
  store :settings, accessors: [ :color, :homepage ], coder: JSON
end

u = User.new(color: 'black', homepage: '37signals.com')
u.color                          # Accessor stored attribute
u.settings[:country] = 'Denmark' # Any attribute, even if not specified with an accessor

# There is no difference between strings and symbols for accessing custom attributes
u.settings[:country]  # => 'Denmark'
u.settings['country'] # => 'Denmark'
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.