2017-11-01 1 views
1

ActiveRecord 모델에 링크 된 데이터베이스 뷰가 있습니다. 그것은 true 또는 false1 또는 0 해석 아니에요데이터베이스 뷰의 필드를 부울 대신 정수로 처리하는 ActiveRecord 모델

[ 
    [0] #<AdherenceActivity:0x007fec986b5328> { 
     :adherence_date => Wed, 01 Nov 2017, 
      :patient_id => 10000, 
       :morning => 0.0, 
      :afternoon => 1.0, 
       :evening => 1.0, 
       :night => nil 
    } 
] 

반환 AdherenceActivity.all 나는 모델을 호출 할 때. 어떻게 1.0 또는 0.0 대신 부울을 반환하도록 모델을 업데이트 할 수 있습니까?

대한 명확한

편집,이 데이터베이스 뷰가 아닌 테이블입니다. 이 아무런 응답이없는 것처럼 여기 DB보기 (오라클 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 

레일 5.1, 루비 2.4.1

+0

보기를 변경할 수 있습니까? 'sum'은 보통'numeric' 타입을 생성합니다. 따라서'1.0'과'0.0' 값을 생성합니다. 오라클 어댑터는 (MySQL과 같은) 부울에 대해 일종의 작은 정수를 사용합니까, 아니면 오라클에 기본 부울 유형이 있습니까? 기본적으로,'sum'을 boolean을 생성하는 무언가 (해당 유형이 사용 가능한 경우)로 바꾸거나 타입 캐스트를 추가해야합니다. –

+0

@muistooshort 불행히도. Oracle은 부울 데이터 유형을 지원하지 않습니다. ActiveRecord는 마이그레이션에서 데이터 유형을 지정한 경우 true/false로 해석합니다. 이것은 뷰이므로 AR에 부울 (또는 오히려 내 질문입니다.이 필드를 부울로 해석하는 방법은 무엇입니까?) – theartofbeing

+0

어떻게 뷰와 상호 작용합니까? 단순히 '아침', '오후', ... 방법을 무시할 수 있습니까? –

답변

0

이, 내 2cents을 줄 것이다. 나는

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 

이 '사실'과 '거짓'이 루비에 자신의 별도의 수업을 .. 내가 이것에 대해 이동하는 방법과이 유형 클래스에 자신을 정의를 추가하고 다음과 같이 게터/세터를 사용할 생각합니다. 이것이하는 일은 'false'클래스의 경우 0.0을 반환하고 'true'클래스의 경우 1.0을 반환하는 각 클래스의 끝 부분에 새 메서드 (to_f)를 추가하는 것입니다. 더 시각적 인 설명은

, 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에 클래스가 0인지 아닌지 검사합니다. (0.zero == 사실 그래서 예를 들어 0.zero하지, 그 반대를해야합니까?.?)



추가 제공 :
내가 방법을 추가하는 것이 좋습니다 때문에 명시된 바와 같이 복잡한 사례가 생기기 시작하면 DRY가 짧고 단정합니다.
변환 할 부울 값이 많다고 가정 해보십시오.

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 

희망이 있습니다.

+0

이것은 내가 오늘 일찍 끝났던 길입니다. 나는 우리 모두가이 결론에 도달했기 때문에 당신에게 요점을 줄 것이다. 여분의 신용 방법은 영리하지만, 아침/오후/저녁/밤 방법을 명시 적으로 명확하게 정의했습니다. FWIW DB 뷰이고 값을 변경할 수 없으므로 setter 메소드가 필요하지 않습니다. – theartofbeing

+0

이것은 또한 'nil'값을 처리하고'false' 대신'nil'을 반환해야합니다. 나는 아침을 꾸몄다. super.nil?을 반환합니다. 슈퍼 == 1' – theartofbeing

+0

@ theartofbeing 그래, 난 아무것도 잊어 버렸다. 이 작업을 수행하는 또 다른 방법은 DB 값이 1, 0, nil이 될 것임을 알기 때문에 rescue nil (업데이트 된 ans.)을 추가하는 것입니다. If/Then은 훨씬 더 명백합니다. 다행 이네. –

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 
관련 문제