2016-07-06 14 views
0

Ich verwende Rails 4 und habe ein Article Modell mit answer, side_effects und benefits als Attribute.Interpolation der Schlüssel eines Attributs vor dem Speichern

Ich versuche, eine before_save Methode zu erstellen, die automatisch auf die Nebenwirkungen und Vorteile untersucht und Links erstellt, die einem anderen Artikel auf der Website entsprechen.

Anstatt zwei praktisch identische Methoden zu schreiben, eine für Nebenwirkungen und eine für Vorteile, würde ich gerne die gleiche Methode verwenden und überprüfen, um sicherzustellen, dass das Attribut ungleich answer ist.

Bisher habe ich so etwas wie dieses:

before_save :link_to_article 

private 

def link_to_article 
    self.attributes.each do |key, value| 
    unless key == "answer" 
     linked_attrs = [] 
     self.key.split(';').each do |i| 
     a = Article.where('lower(specific) = ?', i.downcase.strip).first 
     if a && a.approved? 
      linked_attrs.push("<a href='/questions/#{a.slug}' target=_blank>#{i.strip}</a>") 
     else 
      linked_attrs.push(i.strip) 
     end 
     end 
     self.key = linked_attrs.join('; ') 
    end 
    end 
end 

, aber ich mag, dass auf dem Schlüssel Verkettungs gibt mir ein undefined method 'key'.

Wie kann ich interpolieren im Attribut?

Antwort

1

in diesem Bit: self.key Sie fordern, dass es buchstäblich eine Methode namens key aufrufen, aber was Sie wollen, ist, den Methodennamen aufzurufen, der im variablen Schlüssel gespeichert ist.

können Sie stattdessen verwenden: self.send(key), aber es kann ein wenig gefährlich sein. Wenn jemand ein neues Formular in seinem Browser hackt, um Ihnen das Attribut mit dem Namen delete! zu senden, wollen Sie nicht, dass es versehentlich mit send aufgerufen wird. Daher ist es besser, read_attribute und write_attribute zu verwenden.

Beispiel unten:

def link_to_article 
    self.attributes.each do |key, value| 
    unless key == "answer" 
     linked_attrs = [] 
     self.read_attribute(key).split(';').each do |i| 
     a = Article.where('lower(specific) = ?', i.downcase.strip).first 
     if a && a.approved? 
      linked_attrs.push("<a href='/questions/#{a.slug}' target=_blank>#{i.strip}</a>") 
     else 
      linked_attrs.push(i.strip) 
     end 
     end 
     self.write_attribute(key, linked_attrs.join('; ')) 
    end 
    end 
end 

Ich würde auch nur die erlaubte Menge von Attributen ermöglicht Sie sicherstellen, dass mit starken Eigenschaften in der Steuerung empfehlen.


OLD (bevor ich wusste, dass dies auf alle Attribute verwendet werden sollte)

Das heißt ... warum Sie durch jedes einzelne Attribut gehen und nur etwas tun, wenn das Attribut answer genannt wird? Warum nicht einfach die Attribute durchgehen und direkt auf die Antwort schauen?

zB:

def link_to_article 
    linked_attrs = [] 
    self.answer.split(';').each do |i| 
    a = Article.where('lower(specific) = ?', i.downcase.strip).first 
    if a && a.approved? 
     linked_attrs.push("<a href='/questions/#{a.slug}' target=_blank>#{i.strip}</a>") 
    else 
     linked_attrs.push(i.strip) 
    end 
    end 
    self.answer = linked_attrs.join('; ') 
end 
+1

das ist genau das, was ich brauche .. ich danke Ihnen sehr. Und ich möchte diese Methode auf alle anderen Attribute als Antwort ausführen ... deshalb bin ich durch. Danke nochmal! @Taryn – Kathan

+0

ah cool rechts - das war nicht klar aus dem Code gegeben. Froh, dass es geholfen hat :) –

+0

Noch eine Frage an dich bevor ich die Antwort akzeptiere ... wie kann ich den Attributen einen neuen Wert zuweisen? 'self.send (key) =" neuer Wert "' funktioniert nicht. – Kathan