ActiveRecord: Vorsicht bei der Massenänderung von Attributen

Rails bietet einfache Möglichkeiten um einem Objekt alle benötigten Attribute zuzuweisen. Einem ActiveRecord Model können z.B. schon bei der Instanziierung alle gewünschten Attribute aus den Request-Parametern (z.B. aus einem Formular) übergeben werden. Dieses Vorgehen nennt sich im Rails-Jargon „Mass-assignment“.

Nehmen wir an wir haben ein Model „Comment“, dass die Kommentare von Benutzern einer Webseite speichert. Um Spam vorzubeugen, sollen alle Kommentare erst nach redaktioneller Überprüfung angezeigt werden, weshalb das Model ein Attribut „reviewed“ besitzt. Nur wenn dieses den Wert „1“ hat, wird der Kommentar öffentlich angezeigt.
In der Methode für die Speicherung eines neuen Kommentars steht nun folgender Code:

  1. @comment = Comment.new(params[:comment])

Würde der Anwender den Request nun so manipulieren (z.B. durch das Einfügen eines weiteren Feldes im HTML-Formular), dass dem Host der Parameter params[:comment][:reviewed] mit dem Wert „1“ übergeben wird, wäre die redaktionelle Prüfung umgangen.

Um das zu verhindern, gibt es in ActiveRecord die Methode attr_accessible. Mit dieser kann eine Whitelist der Attribute erstellt werden, die durch Mass-assignment verändert werden dürfen. Die Methode attr_protected bietet die selbe Funktionalität, jedoch mit einem Blacklist-Verfahren, d.h. es werden Attribute definiert, die nicht verändert werden dürfen.

Im Beispiel der Kommentare, müsste man also im Model „Comment“ diesen Code hinterlegen:

  1. attr_protected(:reviewed)

Dann kann das Attribut nur noch mit dem direkten Zugriff manipuliert werden z.B:

  1. comment.reviewed = true

Ich persönlich bevorzuge übrigens das Whitelist-Verfahren, da somit Flüchtigkeitsfehler bei der Entwicklung vermieden werden können ;-)

Share

Praktische Einzeiler In Ruby

Hier ein kurzer Tipp um den Quellcode in Rails bzw. Ruby etwas übersichtlicher zu gestalten.

In dem man in Ruby einer Anweisung eine Bedingung mittels if oder unless nachstellt, kann bestimmt werden, ob die Anweisung ausgeführt wird oder nicht.

Das heißt derartiger Code

  1. if @category_id == '1'
  2.    @title = 'Home'
  3. end

wird ersetzt durch:

  1. @title = 'Home' if @category_id == '1'

Bei Verwendung von unless statt if wird die Negativität der Bedingung geprüft.

Weiterhin können mit dem Schlüsselwort and zwei Anweisungen miteinander verknüpft werden.  Ich nutze das besonders oft um die Weiterleitung und die Übergabe einer Flash-Nachricht miteinander zu verbinden:

  1. flash[:error] = 'Objekt nicht gefunden' and redirect_to(index_path)
Share

Javascript: Mausposition bestimmen

Das Ermitteln der Mausposition mittels Javascript hat sich für mich als nicht ganz einfach erwiesen.
Ich wollte die Mausposition auf einem Bild bestimmen. Leider müssen hier für unterschiedliche Browser wieder unterschiedliche Methoden angewendet werden.
Nach langem Suchen und Probieren habe ich endlich eine Funktion gebastelt, die ich im Firefox 3.5, Opera 10, Internet Explorer 8 und Internet Explorer 6 erfolgreich getestet habe.

  1. function mouse_pos(e, id){
  2.    ievar = typeof(document.all)=='object'?2:0;
  3.    x = e.clientX;
  4.    y = e.clientY;
  5.    i = document.getElementById(id);
  6.    xpos = x – i.offsetLeft – ievar;
  7.    ypos = y – i.offsetTop – ievar;
  8.    return [xpos, ypos];
  9. }

Als Übergabeparamter werden das Event und die ID des Bildes erwartet. Zurückgegeben wird ein Array in der Form [xpos, ypos].

Share