2012-02-21 18 views
7

Mam 3 pola w mojej formie, których nie ma w mojej bazie danych: opening_type, opening_hours, opening_minutes. Chcę zaktualizować główny atrybut "otwarcie" (w bazie danych) tymi 3 polami.Szyny - Dodaj atrybuty nie w modelu i atrybut modelu aktualizacji

Próbowałem wielu rzeczy, które nie działają.

Właściwie mam:

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 

Próbowałem dodając coś takiego:

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 

Ale metody dostępowe nie są nazywane i myślę opening_type, opening_hours, opening_minutes były puste zbyt jeśli dostępowych zostały nazwane ...

Myślę, że nie potrzebuję oddzwaniania before_save i powinienem to przepisać akcesorów.

Uwagi: - Rails 3.0.5, - opening_type,:,: opening_minutes opening_hours mogłyby być pusty

EDIT: I uaktualniony mój kod

Odpowiedz

15

Zauważ, że attr_reader, attr_writer i attr_accessor tylko makr do definiowania własnych metod.

# 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) 

W tej chwili wasze metody setter nie robi nic szczególnego, więc jeśli po prostu przejść do attr_accessor Twój kod będzie czystsze.

Innym problemem jest to, że twoja metoda opening= nigdy nie jest wywoływana, a to ma sens, ponieważ w twoim kodzie nie ma nigdzie go wywoływać. To, czego naprawdę chcesz, to to, że twój otwór zostanie ustawiony po ustawieniu wszystkich poszczególnych części. Teraz nie ma trywialny sposób, aby to zrobić, ale Rails ma before_validation zwrotnego, gdzie można umieścić kod, który biegnie po wartości zostały ustawione ale przed walidacja działa:

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

Uwaga ta odpowiedź zakłada, że ​​chcesz tylko przechowywać połączone pole 'opening' w bazie danych. Innym podejściem byłoby przechowywanie poszczególnych komponentów w bazie danych i dynamiczne budowanie połączonego ciągu na żądanie. W zależności od Twoich wymagań, które mogą być dla Ciebie lepszym rozwiązaniem. – Gareth

+0

Otrzymuję tę bazę danych z polem otwierającym. Ta baza danych jest synchronizowana z aplikacją na smartfona i nie mogę zmienić jej struktury, aby przechowywać 3 różne pola. ;-) Problem z wywołaniem zwrotnym before_validation polega na tym, że nie zajmujesz się przypadkiem, kiedy mamy zamiar edytować formularz ... i gdzie muszę uciąć pole otwierające w 3 vars ... dla formularza. Wiem, że mogę to zrobić ręcznie, ale pomyślałem, że było lepsze podejście do tego, aby to zrobić z akcesoriami ... –

+0

Wszystko prawda, ale twoja sugestia pominięcia 'otwarcia =' złamie wiele rzeczy. Poza tym, bardzo pomysłowym pomysłem jest posiadanie metody ustawiającej, która całkowicie odrzuca parametr, który jest przekazywany. Lepiej mieć oddzielną metodę (jak moje 'set_opening'), która wyjaśnia, co robi. Nie musisz * mieć * używać before_validation, aby wywołać tę metodę, ale naprawdę polecam, że jest to osobna metoda. – Gareth

0

zamiast

attr_reader :opening_type, :opening_hours, :opening_minutes 

trzeba

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

hf ...

// Są: opening_type,: opening_hours,: opening_minutes real fields? Jeśli tak, potrzebujesz tego?

attr_accessor: otwarcie attr_reader: otwarcie

+0

OK, zmieniłem na attr_accessor. Ale akcesory otwierające nie są nazywane ... –

+0

patrz aktualizacja, .... – davidb

+0

Nie. Prawdziwe pole to "otwieranie" w mojej bazie danych. Muszę połączyć 3 pola wysłane z mojego formularza: opening_type, opening_hours, opening_minuts, aby wypełnić główne pole "opening". Te 3 pola nie znajdują się w bazie danych. Zaktualizowałem pierwszy post. –

Powiązane problemy