2010-11-16 27 views
13

Ho prevenire aggiornamenti di alcuni modelli utilizzando questo nel modello:Come posso non consentire gli aggiornamenti tranne per un campo?

def update 
    self.errors.add_to_base("Cannot update a #{ self.to_s }") 
end 

ora sto scrivendo un plugin che fornisce alcune funzionalità in più per il modello, e ho bisogno di aggiornare un campo in modello. Se non fossi utilizzando un plugin Vorrei farlo direttamente nel modello ...

def update 
    if self.changed == ['my_field'] 
    super 
    else 
    self.errors.add_to_base("Cannot update a #{ self.to_s }")  
    end 
end 

non posso fare lo stesso dal mio plug-in quanto non so se il comportamento di aggiornamento è il default ActiveRecord , o è stato sovrascritto per impedire aggiornamenti. C'è un altro modo per prevenire gli aggiornamenti dei record mentre mi consente di eseguire l'override per un campo specifico (e solo nell'istanza in cui il mio plugin è applicato a questo modello).

risposta

10

In primo luogo, si dovrebbe utilizzare un callback before_update per quel genere di cose piuttosto che un aggiornamento forzato. In secondo luogo, è possibile memorizzare gli attributi aggiornabili sul modello e quindi aggiornarli con il plug-in. Ho appena scritto questo nel browser, quindi potrebbe essere sbagliato.

attr_accessor :updatable_attributes 
    before_update :prevent_update 

    private 
    def prevent_update 
    return true if self.changed == self.updatable_attributes 
    self.errors.add_to_base "Cannot update a #{ self.to_s }" 
    false 
    end 
end 
+0

Grazie. Mi sono reso conto che anche i modelli che richiedono la mia logica prevent_update sono quelli che richiedono il plug-in, quindi ho spostato l'intero lotto nel plug-in, utilizzando un filtro before_update come suggerisci. – Nick

+4

In rails 3. *, aggiungere l'errore tramite 'self.errors.add: base," Can not update ... "' – ronen

+1

Penso che probabilmente si voglia che la clausola if sia restituita true se self.changed | self. updatabale_attributes == self.updatabale_attributes' in modo da poter aggiornare anche un sottoinsieme degli updatable_attributes. – Timo

0

È questo per prevenire l'assegnazione di massa? Would attr_accessible/attr_protected non fa quello che ti serve?


Modifica, solo per illustrare il punto generale sulla richiamata.

+0

No, è necessario applicare le regole aziendali a livello di modello. Facendo attr_readonly per ogni campo tranne uno potrebbe fare il lavoro, ma è piuttosto prolisso. – Nick

+0

Che ne dici di un callback before_validation? È possibile verificare quali attributi sono stati modificati e se il modello è nuovo e quindi impedire l'aggiornamento? – allan

+0

Non sono sicuro di aver compreso completamente il tuo suggerimento ... stai dicendo di aggiungere una callback before_validation nel modello che impedirà gli aggiornamenti. Quindi nel mio plugin cosa devo fare per consentire un aggiornamento su un campo? – Nick

4

ritardo al gioco qui, ma per le persone la visualizzazione di questa domanda, è possibile utilizzare attr_readonly per consentire la scrittura su un campo di creare, ma non permettendo aggiornamenti.

Vedi http://api.rubyonrails.org/classes/ActiveRecord/ReadonlyAttributes/ClassMethods.html

penso che è disponibile da Rails 2.0

La parte difficile è, se si dispone di tutti gli attributi che sono attr_accessible bisogna elencare la vostra leggere gli attributi solo lì anche (o si ottiene un errore di messa assegnazione sul creare):

class Post < ActiveRecord::Base 
    attr_readonly :original_title 
    attr_accessible :latest_title, :original_title 
end 
+0

mdkirby, puoi dare un'occhiata a questo? Sento che è collegato a questa risposta. http://stackoverflow.com/questions/33357501/rails-attribute-changes-in-spite-of-not-being-in-form –

0

mi basta usare i binari params.require metodo per whitelist gli attributi che si desidera consentire.

def update 
    if @model.update(update_model_params) 
    render json: @model, status: :ok 
    else 
    render json: @model.errors, status: :unprocessable_entity 
    end 
end 

private 
    def update_prediction_params 
    params.require(:model).permit(:editable_attribute) 
    end 
Problemi correlati