Sebastians Blog http://sgaul.de Neues aus den Softwareminen... Sun, 30 Aug 2015 17:11:10 +0000 de-DE hourly 1 http://wordpress.org/?v=4.3 ActiveAdmin: Standard-Datumsformat ändern http://sgaul.de/2015/08/30/activeadmin-standard-datumsformat-aendern/ http://sgaul.de/2015/08/30/activeadmin-standard-datumsformat-aendern/#comments Sun, 30 Aug 2015 17:05:49 +0000 http://sgaul.de/?p=2774 Weiterlesen ]]> ActiveAdmin erkennt und formatiert die meisten Zeit- und Datumsangaben. In Tabellen kann es jedoch störend sein, wenn das Datum mit dem ausgeschriebenen Wochentag beginnt: Es frisst Platz und sorgt aufgrund unterschiedlicher Länge vor allem in Tabellen für eine ungleichmäßige Ausrichtung. Mit den Standardeinstellungen von ActiveAdmin und Rails-I18n ist das leider der Fall. Ich ändere das Format daher meist auf etwas wie 30.08.2015, 13:39 Uhr.

Hierfür ändere ich das Format, das ActiveAdmin für die Lokalisierung verwendet, auf default. Im vorgegebenen Initializer steht die Konfiguration aktuell nicht drin, so dass ich es am Ende ergänze:

ActiveAdmin.setup do |config|
  # ...
  config.localize_format = :default
end

In den Lokalisierungsdateien muss das entsprechende Format für Datum und Zeit konfiguriert sein:

de:
  date:
    formats:
      default: "%d.%m.%Y"
      long: "%e. %B %Y"
      short: "%e.%m."
  time:
    formats:
      default: "%d.%m.%Y, %H:%M Uhr"
       long: "%A, %d. %B %Y, %H:%M Uhr"
       short: "%d.%m., %H:%M Uhr"

]]>
http://sgaul.de/2015/08/30/activeadmin-standard-datumsformat-aendern/feed/ 0
ActiveAdmin verstehen: Von der Application zur ResourceDSL http://sgaul.de/2015/08/29/activeadmin-verstehen-von-der-application-zur-resourcedsl/ http://sgaul.de/2015/08/29/activeadmin-verstehen-von-der-application-zur-resourcedsl/#comments Sat, 29 Aug 2015 19:05:20 +0000 http://sgaul.de/?p=2767 Weiterlesen ]]> ActiveAdmin ist gut dokumentiert und auch ohne Verständnis der Interna gut zu benutzen. Spätestens wenn man eigene Erweiterungen schreiben möchte, muss man aber verstehen, wie die Engine funktioniert. Ein Anfang für Version 1.0.0.pre1:

Das Modul ActiveAdmin realisiert mittels class << self eine singleton-ähnliche Instanz von ActiveAdmin::Application:

module ActiveAdmin
  class << self
    def application
      @application ||= ::ActiveAdmin::Application.new
    end

Beim Setzen der Routen in der routes.rb wird automatisch load! ausgelöst:

module ActiveAdmin
  class Application

    def routes(rails_router)
      load!
      router.apply(rails_router)
    end

Dieses lädt alle Dateien (üblicherweise app/admin/*) und erzeugt den Default-Namespace :admin:

    def load!
      files.each{ |file| load file }
      namespace(default_namespace)
    end

Die Admin-Dateien registrieren Ressourcen mittels ActiveAdmin.register Resource. Das Modul delegiert dies an die Application, diese an den Namespace. Hier wird eine zur Klasse passende ÀctiveAdmin::Resource erstellt, die im weiteren Kontext meist als config auftritt:

module ActiveAdmin
  class Namespace
    def register(resource_class, options = {}, &block)
      config = find_or_build_resource(resource_class, options)
      parse_registration_block(config, resource_class, &block) if block_given?

Der Block, der beim Anlegen der Ressource angegeben wurde, wird als eine Instanz von ActiveAdmin::ResourceDSL, welcher die config der Ressource zur Verfügung steht.

    def parse_registration_block(config, resource_class, &block)
      config.dsl = ResourceDSL.new(config, resource_class)
      config.dsl.run_registration_block(&block)
    end

Bei der Beschreibung einer Ressource stehen somit die Methoden von ActiveAdmin::ResourceDSL und der Oberklasse ActiveAdmin::DSL zur Verfügung:

module ActiveAdmin
  class ResourceDSL < DSL
    def initialize(config, resource_class)
      @resource = resource_class
      super(config)
    end

    def belongs_to(target, options = {})
    def scope(*args, &block)
    def permit_params(*args, &block)
    def index(options = {}, &block)

Zudem bietet der ActiveAdmin::Resource unter config weitere Metainformationen:

module ActiveAdmin
  class Resource
    attr_reader :resource_class_name
    attr_reader :member_actions
    attr_reader :collection_actions

    include Base
    include ActionItems
    include Authorization
    include Controllers
    include Menu
    include Naming
    include PagePresenters
    include Pagination
    include Scopes
    include Includes
    include ScopeTo
    include Sidebars
    include Routes

    def resource_class
    def decorator_class
    def resource_table_name
    def resource_column_names
    def defined_actions
    def find_resource(id)

Neben Ressourcen kennt ActiveAdmin noch das Konzept der Pages. Deren Initialisierung funktioniert im Wesentlichen ähnlich, nur dass hier eine spezielle ActiveAdmin::PageDSL verwendet wird und als config eine ActiveAdmin::Page dient.

Wenn möglich, werden die für eine Konfiguration möglichen Implementierungen schon bei der Initialisierung von ActiveAdmin erzeugt (etwa Methoden im Ressourcen-Controller). Von Laufzeitdaten abhängige Elemente werden meist in Konfigurationsobjekte gepackt. Diese speichern u.a. Blöcke, die dann zur Laufzeit mit den benötigten Daten ausgeführt werden können. Der Vorgang der Initialiserung ist somit abgeschlossen.

]]>
http://sgaul.de/2015/08/29/activeadmin-verstehen-von-der-application-zur-resourcedsl/feed/ 0
10 Tote, zum Glück nur Männer! http://sgaul.de/2015/08/16/10-tote-zum-glueck-nur-maenner/ http://sgaul.de/2015/08/16/10-tote-zum-glueck-nur-maenner/#comments Sun, 16 Aug 2015 10:04:33 +0000 http://sgaul.de/?p=2764 Weiterlesen ]]> Ich habe gerade eine interessante Kritik an Star Wars Episode II gesehen. Hier wird auf Anakin Skywalkers Geständnis eingegangen, dass er im Sandmenschen-Dorf nicht nur die Männer, sondern auch Frauen und Kinder getötet hätte. Dass ein angeblich moralpachtender Jedi in spe den Tot von Männern relativiert, indem er den Tot von Frauen und Kindern gegenüberstellt, empfanden komischerweise weder Filmschaffer Lucas noch Kritiker ungewöhnlich. Kein Wunder, kennt man diese Form sexistischer Moral nur zu gut aus den Medien:

Unglücksmeldung:
„22 Tote, darunter Frauen und Kinder.“
Warum ist das wichtig?
Ich warte, daß es mal heißt:
„10 Tote, zum Glück nur Männer!“

Volker Pispers

Im Seerecht scheint der vergleichbare Anachronismus „Frauen und Kinder zuerst!“ mittlerweile behoben zu sein. Hier bekommt üblicherweise derjenige als erster Hilfe, der sie am meisten benötigt. Es geht voran…

]]>
http://sgaul.de/2015/08/16/10-tote-zum-glueck-nur-maenner/feed/ 0
Require und Rails http://sgaul.de/2015/06/28/require-und-rails/ http://sgaul.de/2015/06/28/require-und-rails/#comments Sun, 28 Jun 2015 20:13:25 +0000 http://sgaul.de/?p=2761 Weiterlesen ]]> Rails‘ Autoloading macht einen guten Job, so dass man Abhängigkeiten selten per Hand auflösen muss. Will man aber etwa eine bestehende Modelklasse aus einer Engine öffnen um eigenen Code zu ergänzen, so muss das Original notwendigerweise vorhanden sein:

# userengine/app/models/user

class User < ActiveRecord::Base
  belongs_to :user_group
end
# railsapp/app/models/user

require User::Engine.root.join('app', 'models', 'user')

class User < ActiveRecord::Base
  belongs_to :user_group
end

Dies wird vor allem während der Entwicklung zu Problemen führen, da Rails bei einer Änderung die Klasse zurücksetzt und nur die geänderte Datei neu lädt. Die andere Klassendefinition geht verloren, was zu merkwürdigen Ergebnissen führen kann.

Die Lösung für Rails ist ein spezielles Require, welches sich mit Autoloading verträgt:

# railsapp/app/models/user

require_dependency User::Engine.root.join('app', 'models', 'user')
# ...

Im Rails-Guide wird Single-Table-Inheritance als weiteres Einsatzgebiet genannt.

]]>
http://sgaul.de/2015/06/28/require-und-rails/feed/ 0
Weniger Abstraktion ist manchmal mehr http://sgaul.de/2015/04/05/weniger-abstraktion-ist-manchmal-mehr/ http://sgaul.de/2015/04/05/weniger-abstraktion-ist-manchmal-mehr/#comments Sun, 05 Apr 2015 11:47:08 +0000 http://sgaul.de/?p=2749 Weiterlesen ]]> Zunächst war ich kritisch: Kann ein Konferenzbeitrag über Routing-Ansätze brauchbare Erkenntnisse bieten? Schlussendlich ist das Routing ein sehr kleiner Teil und Rails liefert einen funktionierenden Ansatz mit. Performance-Sprünge im gesamten Kontext sind nicht zu erwarten.

Interessant finde ich aber, wie durch das Entfernen der Abstraktion zwischen Router und Controller wesentliche Konzepte vereinfacht werden können. So lassen sich die unschönen Before-Action-Hooks samt Only-Beschränkungen viel eleganter ausdrücken:

route.is 'users' do
  authorize_user_session!

  route.get do
    @users = User.all
    view(:index)
  end

  route.is ':id' do |id|
    @user = User.find(id)
    
    route.get do
      view(:edit)
    end
    
    route.post do
      @user.update(params[:user])
      redirect_to action: :show
    end
  end
end

Dieser verschachtelte Ansatz erlaubt einen intuitiveren Blick auf das Geschehen, als es beispielsweise bei stark getrennten Ansätzen wie Rails der Fall ist:

# Routes

resouces :users, only: [:index, :show, :update]

# UsersController

before_action :authorize_login
before_action :assign_user, only: [:show, :update]

def index
  @users = User.all
end

def edit
end

def update
  @user.update(params[:user])
  redirect_to action: :show
end

private

def assign_user
  @user = User.find(params[:id])
end

Wer sich für einen solchen Routing-Tree-Ansatz interessiert, sollte sich einmal Roda ansehen.

]]>
http://sgaul.de/2015/04/05/weniger-abstraktion-ist-manchmal-mehr/feed/ 0
Konkatenation von Ruby-String-Literalen http://sgaul.de/2015/03/06/konkatenation-von-ruby-string-literalen/ http://sgaul.de/2015/03/06/konkatenation-von-ruby-string-literalen/#comments Fri, 06 Mar 2015 14:24:59 +0000 http://sgaul.de/?p=2745 Weiterlesen ]]> Ich bin gerade über folgende Code-Zeile gestolpert und dachte schon etwas hilfreichem auf der Spur zu sein:

irb
2.1.3 :010 > "aaa" "bbb"
 => "aaabbb"

Es wirkt, als füge Ruby aufeinanderfolgende Strings automatisch zusammen. Leider ist diese Funktion auf reine Stringliterale beschränkt,  so dass sie in der Praxis leider kaum einen Nutzen haben dürfte:

2.1.3 :018 > "aaa" 3.to_s
SyntaxError: (irb):18: syntax error, unexpected tINTEGER, expecting end-of-input
"aaa" 3.to_s
       ^
       from ~/.rvm/rubies/ruby-2.1.3/bin/irb:11:in `<main>'

Schade drum, dennoch interessant zu wissen.

]]>
http://sgaul.de/2015/03/06/konkatenation-von-ruby-string-literalen/feed/ 1
Deponia startet nur noch im Fenster http://sgaul.de/2015/03/05/deponia-startet-nur-noch-im-fenster/ http://sgaul.de/2015/03/05/deponia-startet-nur-noch-im-fenster/#comments Thu, 05 Mar 2015 19:17:39 +0000 http://sgaul.de/?p=2740 Weiterlesen ]]> Am Wochenende habe ich mir bei gog.com das Begrüßungsangebot Deponia für 50 Cent gesichert. Spiel und Humor gefallen mir sehr, doch schon am zweiten Tag wollte es nicht mehr im Vollbild starten. Grund war wohl die viel zu hohe Auflösung, die meinen Laptopbildschirm übertraf und deshalb in einem nur halb sichtbarem Fenster endete.

vim .local/share/Daedalic\ Entertainment/Deponia/config.ini

RESOLUTION = 1600x900

Nach der entsprechenden Korrektur startet es wieder im Vollbild. Mal hoffen dass es so bleibt…

Nachtrag: Ab und an muss ich die Einstellung erneut korrigieren, da  der Wechsel mit und ohne externem Monitor wieder seine Änderungen reinschreibt.

]]>
http://sgaul.de/2015/03/05/deponia-startet-nur-noch-im-fenster/feed/ 0
Kreative Rails-Environments http://sgaul.de/2015/03/05/kreative-rails-environments/ http://sgaul.de/2015/03/05/kreative-rails-environments/#comments Thu, 05 Mar 2015 18:59:00 +0000 http://sgaul.de/?p=2738 Weiterlesen ]]> Rails-Environments sind mächtig, einfach einzurichten und schnell zu wechseln. Fast zu schade sich auf die Klassiker Test, Development und Production zu beschränken. Auch nach zehnmaligem Ändern der Mail-Einstellungen kam bei uns niemand auf die Idee, dass hier eine zweite Development-Umgebung nach Aufmerksamkeit schreit.

Mit erweitertem Horizont sind viele mehr oder weniger nützliche Umgebungen denkbar:

  • Development mit Mail-Versand um Mails im Mailprogramm zu testen
  • Development mit präkompilierten Assets
  • Development mit Production-Datenbank für Notfall-Debugging
  • Testing ohne Class-Cache um in einer Capybara-Session etwas anzupassen
]]>
http://sgaul.de/2015/03/05/kreative-rails-environments/feed/ 0
Pub-/Sub-System Faye: Ein kleiner Test http://sgaul.de/2015/02/18/pub-sub-system-faye-ein-kleiner-test/ http://sgaul.de/2015/02/18/pub-sub-system-faye-ein-kleiner-test/#comments Wed, 18 Feb 2015 16:04:36 +0000 http://sgaul.de/?p=2732 Faye-Server aufsetzen und starten:

docker run -d -p 127.0.0.1:8000:8000 cravler/faye-app

Ein Browsertest auf localhost:8000/pub-sub bescheinigt mir einen Bad Request. Scheint zu laufen.

Auf einen Post-Request gibt es eine bessere Antwort:

curl http://localhost:8000/pub-sub -d 'message={"channel":"/moin", "data":"Moin!"}'
[{"channel":"/moin","successful":true}]
]]>
http://sgaul.de/2015/02/18/pub-sub-system-faye-ein-kleiner-test/feed/ 0
Docker ohne sudo http://sgaul.de/2015/02/17/docker-ohne-sudo/ http://sgaul.de/2015/02/17/docker-ohne-sudo/#comments Tue, 17 Feb 2015 20:32:56 +0000 http://sgaul.de/?p=2728 Weiterlesen ]]> Wie wohl alle Docker-Pakete erfordert auch das PPA von Dotcloud Root-Rechte für alle Aktionen:

me ~ docker ps
 FATA[0000] Get http:///var/run/docker.sock/v1.17/containers/json: dial unix /var/run/docker.sock: permission denied. Are you trying to connect to a TLS-enabled daemon without TLS?

Um dies zu umgehen, kann man den eigenen Nutzer in die Gruppe docker aufnehmen:

sudo gpasswd -a ${USER} docker
sudo service docker restart

Durch die Gruppenänderung muss man sich noch einmal ab- und anmelden, anschließend läuft Docker sudofrei.

]]>
http://sgaul.de/2015/02/17/docker-ohne-sudo/feed/ 0