2012-02-21 13 views
7

Ho 3 campi nel mio modulo che non sono nel mio database: opening_type, opening_hours, opening_minutes. Voglio aggiornare l'attributo principale "apertura" (nel database) con questi 3 campi.Rails - Aggiungere attributi non nel modello e aggiornare l'attributo del modello

Ho provato molte cose che non funzionano.

realtà ho:

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 

Ho provato ad aggiungere qualcosa di simile:

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 

Ma, i metodi di accesso non vengono chiamati e penso opening_type, opening_hours, opening_minutes erano troppo vuoto se le funzioni di accesso sono stati chiamati ...

Penso di non aver bisogno di una richiamata before_save e dovrei fare questa riscrittura degli accessor.

Note: - Rails 3.0.5, - opening_type,: opening_hours, opening_minutes: potrebbero essere vuota

EDIT: ho aggiornato il mio codice

risposta

15

noti che attr_reader, attr_writer e attr_accessor sono solo le macro per definire i propri metodi.

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

Al momento, i vostri metodi setter non stanno facendo nulla di speciale, quindi se si passa a attr_accessor il codice diventerà più pulito.

Il tuo altro problema è che il tuo metodo opening= non viene mai chiamato, e questo ha senso perché non c'è nessuna parte nel tuo codice che lo chiama. Quello che vuoi veramente è che la tua apertura sia impostata dopo che tutte le singole parti sono state impostate. Ora non c'è modo banale per fare questo, ma Rails ha un before_validation richiamata in cui è possibile inserire il codice che viene eseguito dopo che sono stati impostati i valori, ma prima della convalida viene eseguito:

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

Nota questa risposta presuppone che si desidera memorizzare solo il campo 'opening' nel database. Un altro approccio sarebbe quello di memorizzare i singoli componenti nel database e creare la stringa combinata dinamicamente su richiesta. A seconda delle tue esigenze, potrebbe anche essere un approccio migliore per te. – Gareth

+0

Ottengo questo database con il campo di apertura. Questo database si sincronizza con un'app per smartphone e non posso modificare la sua struttura per memorizzare i 3 diversi campi. ;-) Il problema con un callback before_validation è che non si gestisce il caso quando si modifica il modulo ... e dove ho bisogno di troncare il campo di apertura in 3 vars ... per il modulo. So che posso farlo manualmente ma ho pensato che ci fosse un approccio migliore per farlo con gli accessor ... –

+0

Tutto vero, ma il tuo suggerimento di sovrascrivere 'opening =' spezzerà un sacco di cose. Inoltre, è un'idea molto abbozzata avere un metodo setter che scarti totalmente il parametro passato. Meglio avere un metodo separato (come il mio 'set_opening') che chiarisce cosa sta facendo. Non * devi * usare before_validation per chiamare quel metodo ma consiglio seriamente che si tratti di un metodo separato – Gareth

0

invece di

attr_reader :opening_type, :opening_hours, :opening_minutes 

è necessario

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

hf ...

// Sono: opening_type,: opening_hours,: opening_minutes real fields? Se sì, hai solo bisogno di questo?

attr_accessor: apertura attr_reader: apertura

+0

Ok, ho cambiato per attr_accessor. Ma gli accessor di apertura non sono chiamati ... –

+0

vedi aggiornamento, .... – davidb

+0

No. Il vero campo è "aprendo" nel mio database. Ho bisogno di concatcare 3 campi inviati dal mio modulo: opening_type, opening_hours, opening_minuts per riempire il campo principale di "apertura". Questi 3 campi non sono nel database. Ho aggiornato il primo post. –

Problemi correlati