freakcommander » Computer http://www.freakcommander.de Thu, 12 Jun 2014 16:51:21 +0000 de-DE hourly 1 http://wordpress.org/?v=3.9 Bug-Hunting: Download im IE 8 nicht möglich http://www.freakcommander.de/5919/computer/bug-hunting-download-im-ie-8-nicht-m%C3%B6glich/ http://www.freakcommander.de/5919/computer/bug-hunting-download-im-ie-8-nicht-m%C3%B6glich/#comments Fri, 11 Apr 2014 17:49:16 +0000 http://www.freakcommander.de/?p=5919 Es ist schon interessant, dass man sich mit der Fehlerbehebung eines Browsers beschäftigen muss, der vor 5 Jahren das Licht der Welt erblickte und vor 3 Jahren durch den IE 9 abgelöst wurde. 3 Jahre… eine Ewigkeit!

Ein Kundenportal in der Wohnungswirtschaftsbranche kann aber auf den IE 8 nicht verzichten und so bekam ich immer wieder von meinen Kollegen den Hinweis, dass das Kundenportal nicht richtig funktioniert. Die Fehlermeldung der treuen Windows XP-Besitzer und IE8-Surfer beim Download:

Download nicht möglich.

Internet Explorer war nicht in der Lage, diese Seite zu öffnen. Die angeforderte Seite ist entweder nicht verfügbar oder kann nicht gefunden werden. Bitte versuchen Sie es später erneut.

Der Support des Moxiemanagers, den wir für das Kundenportal verwenden, verwies darauf die neueste Version des Moxiemanagers zu installieren, was leider auch nicht half. Ominöserweise funktionierte aber der Download im IE 8 auf der Moxiemanager-Seite. Im Support wurde von “server side issues” gesprochen. Tja, aber welche potentiellen Issues genau? Vom Support kam darauf leider keine Antwort.

Zu diesem Zeitpunkt fiel mir auf, dass mir ein wesentlicher Unterschied zwischen der funktionierenden Moxiemanager-Seite und unseres Kundenportals entgangen war: Wir verwenden SSL, also HTTPS. Erst dank dieses zusätzlichen Puzzlestücks fand ich bei Google ertragreichere Suchergebnisse: So, dass der Internet Explorer 8  nicht über SSL downloaden kann, wenn ein Header Caching verhindert. Mit Fiddler konnte ich bestätigen, dass entsprechende No-Caching Header beim Kundenportal gesetzt werden. Eigenartig, der Quellcode des Moxiemanagers ist nicht für den Header

Pragma: no-cache

verantwortlich. Auch gibt es keine Apache-Konfiguration oder .htaccess-Dateien, die für den Header verantwortlich sein können.

Die Lösung: In der php.ini wird über die Einstellung

session.cache_limiter = nocache

der Header gesetzt. Nach Änderung zu

session.cache_limiter = 

und einem Neustart des Webservers konnte dann auch im IE 8 über SSL heruntergeladen werden.

]]>
http://www.freakcommander.de/5919/computer/bug-hunting-download-im-ie-8-nicht-m%C3%B6glich/feed/ 0
Best of Twitter (22): Der gelbe Sack http://www.freakcommander.de/5903/computer/twitter/best-of-twitter-22-der-gelbe-sack/ http://www.freakcommander.de/5903/computer/twitter/best-of-twitter-22-der-gelbe-sack/#comments Sun, 15 Dec 2013 11:09:20 +0000 http://www.freakcommander.de/?p=5903

Ich: "Wer bringt den gelben Sack runter?" Asiatischer Kollege ruft aus der Küche: "ICH KANN ALLEINE LAUFEN!"

— Freudigarscherregt™ (@sanitario_) December 10, 2013

[via favstar]

]]>
http://www.freakcommander.de/5903/computer/twitter/best-of-twitter-22-der-gelbe-sack/feed/ 0
Best of Twitter (21): Captain Kirk an ISS http://www.freakcommander.de/5804/computer/twitter/best-of-twitter-21-captain-kirk-an-iss/ http://www.freakcommander.de/5804/computer/twitter/best-of-twitter-21-captain-kirk-an-iss/#comments Sat, 05 Jan 2013 09:26:16 +0000 http://www.freakcommander.de/?p=5804

@WilliamShatner Yes, Standard Orbit, Captain. And we're detecting signs of life on the surface.

— Chris Hadfield (@Cmdr_Hadfield) January 3, 2013

[via Nerdcore]

]]>
http://www.freakcommander.de/5804/computer/twitter/best-of-twitter-21-captain-kirk-an-iss/feed/ 0
Rails: Where mit Hash-Bedingung bei Joins http://www.freakcommander.de/5767/computer/rails-where-mit-hash-bedingung-bei-joins/ http://www.freakcommander.de/5767/computer/rails-where-mit-hash-bedingung-bei-joins/#comments Thu, 27 Dec 2012 11:58:59 +0000 http://www.freakcommander.de/?p=5767 Viele Wege führen nach Rom. So auch bei Abfragen in Rails. Es gibt 3 verschiedene Wege, um Konditionen zu formulieren:
  1. String
  2. Array
  3. Hash
class User < ActiveRecord::Base
  def self.authenticate_unsafely(user_name, password)
    where("user_name = '#{user_name}' AND password = '#{password}'").first
  end

  def self.authenticate_safely(user_name, password)
    where("user_name = ? AND password = ?", user_name, password).first
  end

  def self.authenticate_safely_simply(user_name, password)
    where(:user_name => user_name, :password => password).first
  end
end

Die String-Methode ist unsicher, da die Daten nicht bereinigt werden und so SQL-Injections möglich sind.

Die Array-Methode ist sicher und erinnert syntaktisch stark an Prepared Statements.

Die Hash-Methode ist ebenfalls sicher, aber typisch Rails, weil einfach: lediglich ein Hash wird übergeben. Der Schlüssel (key) als Symbol entspricht der Spaltenbezeichnungen der Tabelle und der Wert (value) definiert die Bedingung.
Das Schöne an der Hash-Methode ist neben der Sicherheit, dass das Hash wesentlich einfacher dynamisch berechnet werden kann (als die Array-Methode):

def all_by_employee_or_manager(employee_id=nil, manager_id=nil)
  condition = Hash.new
  condition[:employee_id] = employee_id unless employee_id.blank?
  condition[:manager_id] = manager_id unless manager_id.blank?
  where(condition)
end

Das Problem: NoMethodError

Sobald jedoch in der Abfrage gejoint wird, bekommt man bei einer Hash-Bedingung wie

joins(:employees).where(:employees.name => name)

folgenden Fehler:

NoMethodError: undefined method `name' for :employees:Symbol

Das Problem ist, dass das Symbol :employees.name nicht komplett als Symbol interpretiert wird, sondern nur bis zum Punkt.

Bei der Internetrecherche habe ich für gejointe Abfragen nur Konditionen im String- oder Array-Format finden können, was in meinem Anwendungsfall aber nicht praktikabel war, denn die Konditionen mussten dynamisch berechnet werden.

Die Lösung

Um Konditionen in gejointen Abfragen mit der Hash-Methode anzugeben, muss Ruby klar gemacht werden, dass employees.name komplett als Symbol verstanden werden soll. Das geht so:

joins(:employees).where(:"employees.name" => name)

Einfach, wenn gewusst wie!

]]>
http://www.freakcommander.de/5767/computer/rails-where-mit-hash-bedingung-bei-joins/feed/ 0
Rails: Dynamische Assoziation zwischen verschiedenen Datenbanken http://www.freakcommander.de/5758/computer/rails-dynamische-assoziation-zwischen-verschiedenen-datenbanken/ http://www.freakcommander.de/5758/computer/rails-dynamische-assoziation-zwischen-verschiedenen-datenbanken/#comments Wed, 26 Dec 2012 21:11:38 +0000 http://www.freakcommander.de/?p=5758 Über Assoziationen lassen sich in Ruby on Rails verschiedene Modelle miteinander verbinden und so einfacher Daten abfragen, aktualisieren und einfügen. In diesem Artikel geht es um zwei Aspekte, die ich im Internet nur schwer recherchieren konnte:
  1. Assoziationen zwischen verschiedenen Datenbanken
  2. Dynamische Assoziationen (der Tabellenname des assoziierten Modells ist dynamisch und hängt von einem Attribut ab)

Anwendungsbeispiel

In meinem Fall geht es um das Modell Contact, welches in der Rails-Anwendung die Kontakte/Aufgaben eines Testmieters verwaltet. Pro Kontakt wird in LimeSurvey ein Teilnehmer eines Fragebogens hinterlegt, der den Fragebogen ausfüllen kann. Die eingegebenen Daten des Testmieters sollen in der Rails-Anwendung mit dem Kontakt (Contact) verbunden werden. Dabei gibt es diese Herausforderungen:

  • Die Datenbank, in dem die Tabelle contacts liegt, ist ralv während die Fragebogen-Antworten in der Datenbank limesurvey liegen.
  • Die Fragebogen-Eingaben liegen je nach Kontakt in verschiedenen Tabellen. Der Tabellenname ist z.B. lime_survey_661185, wobei 661185 die ID des Fragebogens in LimeSurvey ist. Die ID des Fragebogens wird im Kontakt gespeichert.

Die Struktur der Tabellen ist also:

wobei der Name der Tabelle lime_survey_* von contacts.fragebogen_id abhängt. Deutlicher wird dieser Aspekt in der Datenansicht:

Assoziationen zwischen verschiedenen Datenbanken

Kümmern wir uns zunächst um diesen einfacheren Part: Modelle aus unterschiedlichen Datenbanken. Als Erstes muss eine zusätzliche Datenbank-Verbindung in /config/database.yml eingerichtet werden:

limesurvey:
adapter: mysql2
encoding: utf8
username: [DBUSER]
password: [DBPASSWORD]
database: limesurvey

Für die Tabellen lime_survey_* wird zudem ein Modell namens LimesurveyData erstellt:

class LimesurveyData < ActiveRecord::Base
  establish_connection :limesurvey
  self.table_name_prefix = 'limesurvey.'
  self.table_name = 'lime_survey_661185'
  has_one :contact, :primary_key => "token", :foreign_key => "token"
end

Betrachten wir den Quellcode zeilenweise:
1. Zeile: Die Klasse erbt von ActiveRecord, womit sie die Funktionen eines Rails-Modells erhält.
2. Zeile: Für die Klasse soll die vorher in /config/database.yml eingerichtete Datenbank-Verbindung verwendet werden.
3. Zeile: Um generell eine andere Datenbank in einer SQL-Abfrage zu spezifizieren, wird folgende Syntax verwendet Datenbank.Tabelle.Spalte. Rails 3.1 spezifiziert standardmäßig nicht die Datenbank in Abfragen, daher wird die Datenbank über den table_name_prefix in allen Abfragen des Modells eingefügt, sodass klar ist, welche Datenbank bei diesem Modell zu verwenden ist.
4. Zeile: Der Tabellenname wird normalerweise aus dem Klassennamen errechnet. In diesem Fall soll zunächst statisch die Tabelle lime_survey_661185 verwendet werden.
5. Zeile: Die Assoziation zu dem Modell Contact wird als 1:1-Beziehung eingerichtet. Dabei wird festgelegt, dass über das Attribut token in beiden Tabellen die Verbindung hergestellt wird.

In der Contact-Klasse wird zusätzlich ebenfalls die Assoziation zur LimesurveyData-Klasse eingerichtet:

class Contact < ActiveRecord::Base
  ...
  has_one :limesurvey_data, :class_name => "LimesurveyData", :primary_key => "token", :foreign_key => "token"
  ...
end

Der table_name_prefix muss in der Contact-Klasse nicht gesetzt werden, da standardmäßig die richtige Datenbank verwendet wird.

Dynamische Assoziationen

Um die dynamische Assoziation, also den richtigen LimesurveyData-Tabellennamen in Abhängigkeit zur Fragebogen-Id zu setzen, haben wir den wichtigsten Befehl bereits in der LimesurveyData-Klasse kennengelernt: self.table_name

Die Frage ist, an welcher Stelle der Tabellenname gesetzt werden muss. Der Tabellenname kann nicht in der LimesurveyData-Klasse definiert werden, weil dort unklar ist, welche Fragebogen-Id für die Assoziation relevant ist. Die Contact-Klasse ist der bessere Kandidat, denn schließlich wird dort die Fragebogen-Id gespeichert. Aber wie kann der Tabellenname eines anderen Modells gesetzt werden? So:

class Contact < ActiveRecord::Base
  ...
  after_initialize :setTablename
  ...
  has_one :limesurvey_data, :class_name => "LimesurveyData", :primary_key => "token", :foreign_key => "token"
  ...
  def setTablename
    LimesurveyData.table_name = "lime_survey_#{self.fragebogen_id}"
  end
  ...
end

Starten wir diesmal in mit der setTablename-Methode in den Zeilen 7-9: Sie setzt den Tabellenname der Ḱlasse LimesurveyData auf den dynamischen Namen.
In Zeile 3 wird diese Funktion als Callback-Funktion definiert, die immer dann ausgeführt wird, wenn die Contact-Klasse initialisiert wurde.

Und das ist alles: Wir können nun ganz einfach von einem Kontakt auf die korrekten Fragebogen-Antworten zugreifen, obwohl die Daten in einer anderen Datenbank liegen und über verschiedene Tabellen verteilt sind.

]]>
http://www.freakcommander.de/5758/computer/rails-dynamische-assoziation-zwischen-verschiedenen-datenbanken/feed/ 1