我有一个数据库视图,我已链接到ActiveRecord模型。当我调用模型AdherenceActivity.all
时,它返回
[
[0] #<AdherenceActivity:0x007fec986b5328> {
:adherence_date => Wed, 01 Nov 2017,
:patient_id => 10000,
:morning => 0.0,
:afternoon => 1.0,
:evening => 1.0,
:night => nil
}
]
它不会将1
或0
解释为true
或false
。如何更新模型以返回布尔值而不是1.0
或0.0
?
修改
为了澄清,这是一个数据库视图,而不是一个表。这是我对DB View(Oracle SQL)的迁移
class CreateAdherenceActivities < ActiveRecord::Migration[5.0]
def up
execute <<-SQL
CREATE VIEW adherence_activities AS
SELECT
adherence_date,
patient_id,
sum(case when scheduled_time = 'morning' then nvl2(acknowledged_at,1,0) end) as morning,
sum(case when scheduled_time = 'afternoon' then nvl2(acknowledged_at,1,0) end) as afternoon,
sum(case when scheduled_time = 'evening' then nvl2(acknowledged_at,1,0) end) as evening,
sum(case when scheduled_time = 'night' then nvl2(acknowledged_at,1,0) end) as night
FROM medication_adherences
GROUP BY adherence_date, patient_id
SQL
end
def down
execute "DROP VIEW adherence_activities"
end
end
Rails 5.1,Ruby 2.4.1
答案 0 :(得分:0)
由于没有回应,我会给出我的2。我认为我会这样做的方法是在Classes类本身中添加定义,然后像这样使用getter / setter ..
class AdherenceActivity < ApplicationRecord
def morning
#do nothing if nil
return if @morning.nil?
#convert to boolean
@morning.to_bool
end
def morning=(val)
super(val.to_f)
end
#And repeat for other boolean values...
end
class FalseClass; def to_f; 0.0 end end
class TrueClass; def to_f; 1.0 end end
class Float; def to_bool; not self.zero? end end
#NOTE: I am unsure what data type the DB/Rails is setting the 1s and 0s to
#But it looks like a float
'true'和'false'在Ruby中有自己独立的类。这样做是在每个类的末尾添加一个新方法(to_f),在'false'类的情况下只返回0.0,在'true'类的情况下返回1.0。
为了更直观的解释, 在irb:
irb(main):001:0> false.class
=> FalseClass
irb(main):002:0> true.class
=> TrueClass
irb(main):008:0> false.to_f
=> 0.0
irb(main):009:0> true.to_f
=> 1.0
然后,就从float返回到boolean的转换而言,将一个类添加到Float,它将检查它是否为零。 (0.zero?== true所以需要相反的,例如。不是0.zero?)
额外信用:
我建议添加所述的方法,因为当你开始涉及更复杂的情况时,它会使事情变得干燥,简短和甜蜜
假设你有很多不同的布尔值要转换。
class AdherenceActivity < ApplicationRecord
#Your list of boolean/float columns
%w[morning afternoon evening night].each do |s|
#Getter methods
define_method(s) do
#do nothing if nil value received
return if self.instance_variable_get("@#{s}").nil?
#Get the instance variable with name, eg. @night
self.instance_variable_get("@#{s}").to_bool
end
#Setter methods
define_method("#{s}=") do |val|
super(val.to_f)
end
end
end
class FalseClass; def to_f; 0.0 end end
class TrueClass; def to_f; 1.0 end end
class Float; def to_bool; not self.zero? end end
#Assuming float data type
希望这有用。
答案 1 :(得分:0)
这与@ brad-ax发布的内容基本相同,但处理nil
案例。我希望在ActiveRecord / Query级别上解决这个问题,因为这不会更改查询的返回值,但会更改我在上午/下午/傍晚/晚上调用对象时返回的值。
我选择@ brad-ax是因为这是正确的做法,但为了清晰起见,我想发布我的解决方案。
def morning
return if super.nil?
super == 1
end
def afternoon
return if super.nil?
super == 1
end
def evening
return if super.nil?
super == 1
end
def night
return if super.nil?
super == 1
end