我有一个:extra_fields
列的模型是:jsonb
数据类型,我想在列中添加attr哈希值,如下所示,但我不确定在这里抛出哈希值'数据类型的语法,如果不在这里什么的是否是投射哈希值数据的最佳做法?
instance = Model.find_or_create_by(ref_id: hash[:ref_id]) do |a|
a.extra_fields = {
'attr1' : hash[:attr1], <-- //possible to cast type here ie ::type ?
'attr2' : hash[:attr2] <--
}
instance.save!
end
额外奖励:我如何将哈希值转换为类型:decimal
,:string
,:boolean
,:date
?
Rails / Rack中的所有传入参数都是字符串。除了仍然有字符串作为值的数组/哈希参数之外。将参数传递给模型时,Rails会执行实际的转换。
您可以使用.to_x
方法将字符串转换为Ruby中的任何其他类型:
irb(main):006:0> "1.23".to_f
=> 1.23
irb(main):007:0> "1.23".to_d
=> #<BigDecimal:7ff7dea40b68,'0.123E1',18(18)>
irb(main):008:0> 1.23.to_s
=> "1.23"
irb(main):008:0> 1.23.to_i
=> 1
Boolean cast是一个Rails功能。你可以这样做:
# Rails 5
ActiveModel::Type::Boolean.new.cast(value)
ActiveModel::Type::Boolean.new.cast("true") # true
ActiveModel::Type::Boolean.new.cast("t") # true
ActiveModel::Type::Boolean.new.cast("false") # false
ActiveModel::Type::Boolean.new.cast("f") # false
# This is somewhat surprising
ActiveModel::Type::Boolean.new.cast("any arbitrary string") # true
# Rails 4.2
ActiveRecord::Type::Boolean.new.type_cast_from_database(value)
# Rails 4.1 and below
ActiveRecord::ConnectionAdapters::Column.value_to_boolean(value)
请注意,这与!
和!!
完成的Ruby布尔强制非常不同。
irb(main):008:0> !!"false"
(irb):8: warning: string literal in condition
=> true
在Ruby中除了nil和false之外的所有内容都是正确的。
日期有点复杂。默认的Rails日期输入使用多参数发送日期的每个部分(年,月,日)以及从这些输入构造日期的特殊设置器。
Processing by PeopleController#create as HTML
Parameters: { "person"=>{"birthday(1i)"=>"2019", "birthday(2i)"=>"2", "birthday(3i)"=>"16"}, ...}
您可以通过以下方式从这些参数构造日期:
date_params = params.fetch(:person).permit("birthday")
Date.new(*date_params.values.map(&:to_i))
什么是投射哈希值数据的最佳做法?
这里没有最好的做法。您应该思考的是使用JSON列。由于您似乎希望将某种模式应用于数据,因此实际创建单独的表和模型可能是个好主意。毕竟你使用的是关系数据库。
JSON列非常适合解决一些复杂问题,如键/值表或存储原始JSON数据,但在建模数据时,它们不应该是您的首选。
请参阅PostgreSQL anti-patterns: Unnecessary json/hstore dynamic columns以获取有关该主题的详细信息。