2012-02-21 2 views
7

내 양식의 마녀가 내 데이터베이스에 없습니다 : opening_type, opening_hours, opening_minutes. 이 3 개의 필드를 사용하여 데이터베이스에서 기본 속성 "opening"을 업데이트하려고합니다.레일 - 모델에없는 속성 추가 및 모델 속성 업데이트

나는 많은 일을 시도했지만 효과가 없습니다. 사실

내가 가진 : 내가 좋아하는 뭔가를 추가하는 시도

attr_accessor :opening_type, :opening_hours, :opening_minutes 

    def opening_type=(opening_type) 
    end 
    def opening_type 
    opening_type = opening.split("-")[0] if !opening.blank? 
    end 

    def opening_hours=(opening_hours) 
    end 
    def opening_hours 
    opening_hours = opening.split("-")[1] if !opening.blank? 
    end 

    def opening_minutes=(opening_minutes) 
    end 
    def opening_minutes 
    opening_minutes = opening.split("-")[2] if !opening.blank?  
    end 

:

def opening=(opening) 
    logger.info "WRITE" 

    if !opening_type.blank? and !opening_hours.blank? and opening_minutes.blank? 
     opening = "" 
     opening << opening_type if !opening_type.blank? 
     opening << "-" 
     opening << opening_hours if !opening_hours.blank? 
     opening << "-" 
     opening << opening_minutes if !opening_minutes.blank? 
    end 
    write_attribute(:opening, opening) 
    end 

    def opening 
    read_attribute(:opening) 
    end 

단, 접근 방법은 전화를 나는 opening_type, opening_hours, opening_minutes이 너무 비어 있었다 생각되는 접근하는 경우 호출되었습니다 ...

난 before_save 콜백이 필요 없어 생각하고 접근자를 다시 작성해야합니다.

참고 : - 레일 3.0.5, - opening_type : opening_hours : opening_minutes가 비어

편집 될 수있다 : 내 코드

답변

15

하는 것으로는 자신의 방법을 정의하는 매크로로. 순간

# attr_reader(:foo) is the same as: 
def foo 
    @foo 
end 

# attr_writer(:foo) is the same as: 
def foo=(new_value) 
    @foo = new_value 
end 

# attr_accessor(:foo) is the same as: 
attr_reader(:foo) 
attr_writer(:foo) 

, 당신의 setter 메소드는 특별한 작업을 수행하지 않는, 그래서 당신은 단지 attr_accessor로 전환 할 경우 코드는 청소기 될 것입니다.

다른 문제는 opening= 메서드가 호출되지 않는다는 것입니다. 이는 코드를 호출하는 코드가 없기 때문에 의미가 있습니다. 당신이 정말로 원하는 것은 개개 부품이 모두 설정된 후에 개업을 설정하는 것입니다. 지금이이 작업을 수행 할 사소한 방법,하지만 레일은 값을 설정 한 후 실행되지만 유효성 검사가 실행되기 전에 코드를 넣을 수 before_validation 콜백 가지고 : 좋아

class Shop < ActiveRecord::Base 

    attr_accessor :opening_type, :opening_hours, :opening_minutes 

    before_validation :set_opening 

    private 
    def set_opening 
    return unless opening_type && opening_hours && opening_minutes 
    self.opening = opening_type + "-" + opening_hours + "-" + opening_minutes 
    end 
end 
+0

참고이 답변은 데이터베이스에 결합 된 'opening' 필드 만 저장한다고 가정한다고 가정합니다. 또 다른 접근법은 개별 구성 요소를 데이터베이스에 저장하고 필요에 따라 동적으로 결합 된 문자열을 작성하는 것입니다. 요구 사항에 따라 더 나은 접근 방식이 될 수도 있습니다. – Gareth

+0

나는이 데이터베이스를 시작 필드와 함께 사용합니다. 이 데이터베이스는 스마트 폰 앱과 동기화되며 3 가지 필드를 저장하기 위해 구조를 변경할 수 없습니다. ;-) before_validation 콜백의 문제점은 폼을 편집 할 때 대소 문자를 처리하지 않는다는 것입니다. 그리고 폼의 3 개의 vars에있는 시작 필드를자를 필요가 있습니다. 나는 그것을 수동으로 할 수 있다는 것을 알고 있지만 접근자를 사용하여 더 나은 접근 방법이 있다고 생각했다 ... –

+0

사실,하지만 'opening ='을 재정의하면 많은 일이 깨질 것이다. 또한 전달 된 매개 변수를 완전히 파기하는 setter 메서드를 사용하는 것이 매우 간단합니다. 내 작업을 명확하게하는 별도의 메서드 (예 :'set_opening ')를 사용하는 것이 좋습니다. 해당 메소드를 호출하기 위해 before_validation을 사용하지 않아도되지만 실제로는 별도의 메소드임을 권장합니다. – Gareth

0

대신

attr_reader :opening_type, :opening_hours, :opening_minutes 

당신이 필요로의 업데이트

attr_accessor :opening_type, :opening_hours, :opening_minutes 
attr_reader :opening_type, :opening_hours, :opening_minutes 

hf ...

// Are : opening_type, : opening_hours, : opening_minutes 실제 필드? 그렇다면 당신은 이것을 필요로합니까?

attr_accessor : 개방 attr_reader : 개방 attr_reader, attr_writerattr_accessor

+0

를, 내가 attr_accessor에 대한 변경을. 그러나 시작 접근자는 호출되지 않습니다 ... –

+0

업데이트를 참조하십시오 .... – davidb

+0

번호. 실제 데이터베이스는 "opening"입니다. 내 양식에서 보낸 3 개의 필드를 연결해야합니다 : opening_type, opening_hours, opening_minuts는 "opening"필드를 채 웁니다. 이 세 필드는 데이터베이스에 없습니다. 첫 번째 게시물을 업데이트했습니다. –