Update (7.11.11 22:11): Updated the post with a link to the “ChiliProject –
Spread the word” thread in the ChiliProject forums which holds
most of the points I’ve dicussed at RailsCamp HH and the RUG::B.
I’ve been to two Ruby and Ruby on Rails focused events in the past week, first
to the RailsCamp Hamburg 2011, then to the monthly meeting of the RUG::B
(the Ruby User Group Berlin), and while I didn’t expect ChiliProject to be
as well known as some other big or popular projects, I was somewhat astonished
and maybe even a little disappointed to see how little even its name was known.
It seems to me that public knowledge and being on people’s mind is something that
we need to work on more than any technical or feature-wise improvements (don’t
get me wrong: those are important too, but pretty useless if no one uses them…).
It really hit me last saturday at the RailsCamp when the schedule for the day
was being discussed. When it was my turn to propose my talk (I had naturally
prepared a short one about ChiliProject and why we had forked Redmine), I first
asked how many people had heard of ChiliProject, then how many didn’t know Redmine.
I estimate there were some 100-130 people present, and the answer to both
questions was less than ten. Now I didn’t expect more than half the people
present to know about ChiliProject, but less than 10% is a really small mindshare.
The interest wasn’t overwhelming either, but I credit that to my somewhat
clumsy introduction to the matter and the very strong lineup otherwise than
to sheer disinterest, so the talk turned into a discussion with people already
using Redmine that have gone a little worried about the project and who were glad
to hear about someone “picking up the slack”, even if it was in the form of a fork.
Then came the RUG::B. I had planned on going anyway and decided to try to
spread the word about ChiliProject there. I reworked the presentation to be more
focused on the technical and community reasons behind the fork (the slides aren’t
available online as some slides might be misinterpreted without the
presentation, the gist of the presentation’s arguments can be found in this
“ChiliProject – Spread the word” thread in the ChiliProject forums) and
presented it to the 30-odd people present. The preliminary
question got roughly the same answer as on the RailsCamp, the interest and
response were great though, including specific questions regarding the
intended “community management” style and praise and admiration for having the
guts to fork instead of just “giving up”.
All in all, I think those two visits showed me that we still have a lot of work
to do in the mindshare area. The visibility of ChiliProject will rise when the
new design (current design proposal here, not final yet) is released and
deployed on some high-profile installations, but this probably won’t be enough.
In addition to that, I plan on going to some european conferences during the next
year (wroc_love.rb, Railsberry and the EuRuKo) and hold presentations
or at least lightning talks about ChiliProject. Interesting times! :–)
Update (1.11.11 22:42): Jonas von den Ubernauten hat mich drauf hingewiesen,
dass man schon mittels gitolite ein Repository über ssh mit mehreren Nutzern
teilen kann, den Post habe ich entsprechend korrigiert. Weiterhin bietet grack
keine wirklichen Vorteile gegenüber dem git-eigenen git-http-backend, den hatte ich
allerdings “vergessen” weil er als ich auf einem anderen Server einen git
smart-http installiert habe nicht in Frage gekommen war, grack schon.
Kahlil Lechelt hat vor ein paar Monaten in seinem Post UberGit schon
gezeigt, wie man Uberspace als privaten git Server über ssh benutzen kann.
Diese Methode hat allerdings den Nachteil, dass man Anderen keinen Zugriff auf
seine Repositories oder mehreren Leuten Schreibzugriff auf ein gemeinsam-genutztes
Repository geben kann. Das Uberspace Wiki beschreibt weiterhin, wie man
gitolite installieren kann und damit über ssh mehreren Nutzern Lese- und/oder
Schreibzugriff auf Repositories geben kann, bzw. wie man
ein Repository über http veröffentlichen kann, hier ist der Schreibzugriff
allerdings ausgeschlossen.
Nun, wem unwohl ist anderen Benutzern Zugriff auf sein ssh zu geben, die
ssh-Konfiguration für die Endanwender zu kompliziert ist und über http
auch schreiben können möchte, dem verschafft grack Abhilfe. grack ist ein in
Ruby geschriebener Wrapper um git selbst, der einen git-smart-http-Server
über den man Repositories lesen und schreiben kann bereitstellt.
Folgendes Kommando installiert grack im eigenen Uberspace:
1
sh < <(curl -s https://raw.github.com/gist/1329025/uberspace-install-grack.sh)
Dieses Kommando führt das unten aufgeführte Skript aus, was:
grack in einen versteckten Ordner .grack in deinem Home-Verzeichnis runterlädt,
in .grack den Ordner repositories erstellt, von wo grack später Repositories
auslesen wird,
einen fcgi-Handler mit der richtigen ruby-Version und grack-Konfiguration für
dich erstellt.
Die durch das Skript erstellte Konfiguration erlaubt Lese- aber keinen Schreibzugriff,
um Letzteren zu erlauben muss in der erstellten ~/fcgi-bin/git.fcgi der Parameter
:receive_pack => false, zu :receive_pack => true, geändert werden. Das
fcgi-Skript kann man auch nach Belieben in einen anderen Host als den default Host
installieren, dafür verweise ich aber auf den FastCGI Artikel im Uberspace
Wiki (dort ist übrigens auch beschrieben wie man ein FastCGI Skript neustarten
kann, was nötig ist nachdem man die Konfiguration geändert hat).
Repositories sollten für grack im bare Format vorliegen. Ein neues Repository
legt man mit git init --bare ~/.grack/repositories/repo_name
an, ein existierendes Repository kann man mit
git clone --bare http://example.com/repo_name ~/.grack/repositories/repo_name
clonen. Die Adresse zu einen so erstellten Repository lautet für mich dann
http://thegcat.virgo.uberspace.de/fcgi-bin/git.fcgi/repo_name, den Account
bzw. Uberhost Namen muss dann jeder für sich anpassen (das Skript gibt die
“Oberadresse” für alle Repositories auch noch mal aus :–) ).
Eine letzte aber wichtige Anmerkung: grack bietet keine Möglichkeit den Zugriff
auf alle oder einzelne Repositories zu verbieten bzw. nur bestimmten Benutzern
zu erlauben, man kann lediglich über die Parameter :upload_pack bzw.
:receive_pack Lese- bzw. Schreib-Operationen für alle Repositories zulassen.
Eine feinere Zugangskontrolle muss noch “vor” grack im Uberhost Apache passieren,
dazu aber später von den Ubernauten oder mir noch was.
tl;dr: Draper wraps the Rails “helper dumps” in objects resulting in namespaced
dumps you have to remember calling. Yay (not).
Disclaimer: I’m no expert on OOP (apart from the basic class at the university
that teaches that “putting code in classes” is good) nor Rails (I learnt ruby and
Rails by myself roughly 2 years ago while tinkering with Redmine (hint: not the
nicest code in the Rails world)), so don’t take my opinion for granted, I just
hope to fuel the discussion a little.
Flashback to pre-Draper times: everyone has a feeling of sorts that the Rails
helpers are probably a bad idea, but they still become the dumping place for
any formatting methods and other stuff you don’t know where else to put. Formatting
methods landed there because having them in your ActiveRecord models made the
models look bloated which made you feel even worse than putting them in the helpers
and/or because what you wanted the method do do wouldn’t work in the model
because models miss the ActionView helpers (link_to et al.). Over time, the helpers
would get bloated, you’d have to add them to an increasing number of views,
maybe even include them in the controllers because you’d put some controller
logic in there or needed view logic in the controller (I’m looking at you,
#to_xml, but that’s a different matter). In the end, everyone would feel bad about
the helpers becoming so big and jumbled together, but it still was better than having all this
stuff in your models or controllers (or views!) and more convenient because you
could even add all helpers to all view and be done with it (provided you didn’t
have any methods with the same names in different helpers).
Enter Draper. It has a nice sounding name, claims to solve an itch Rails
developers have, and uses a catchy sounding OOP pattern everyone has heard
about some time or another as selling point. Problem solved, right? I thought so too at first
(beware of the buzzwords!), but Andreas (@mediafinger) and Uygar’s
(@uygar_gg) presentation at the RailsCamp Hamburg made me realize that the
lurking unease I had about Draper is justified after all. Draper just wraps your
helpers in objects (something you could have easily done before but rightfully
didn’t) thus solving the cross-helper method name collision problem, at the cost of
just a little less hassle than doing it yourself would have been while masking
the pain you’d have had making decorators yourself.
Let’s have a look at an example, first without Draper:
Not really pretty because you have some function twitter_link_for_user that
looks like it should rather belong to the User class (the for_user part of
the method name should be enough of a hint) rather than lurch in the helper,
and you have included the helper in the controller, for example to include the
twitter link in some #to_xml call. If I’m not completely mistaken, Rails helpers
are view helpers, including them in your controllers puts view logic in them,
which kinda renders the whole MVC pattern moot and should be considered a code smell.
You can now get the twitter link for the user by calling @user.twitter_link
and you were able to stop including the helper in the controller, you can even
drop the helper call in the controller if your helper becomes empty. You feel
all fuzzy inside and are comfortable with your code again. The helper is empty
and everything is neatly organized in objects, so it’s all OOP and must thus be
good, right? I don’t think so.
Let me rephrase the above without using Draper (I’m aware Draper does a little
bit more than that, but bear with me):
classUser<ActiveRecord::BaseendclassUserDecoratorincludeActionView::Helpersdefinitialize(user)@user=userenddeftwitter_linklink_to"https://twitter.com/#{@user.twitter_nickname}"enddefmethod_missing# try calling on @user what we didn't implement hereendendclassUserController<ApplicationControllerbefore_filter:find_user,:only=>[:show,:update,:edit,:destroy]privatedeffind_user@user=UserDecorator.new(User.find(params[:id]))endendmoduleUserHelperend
How does it look without the nice syntax Draper brings? There’s an explicit
call to ActionView::Helpers in something directly called by the controller.
It doesn’t feel so warm and fuzzy after all, does it? Here’s the slide from the
aforementioned presentation which made me realize that you’re effectively
squeezing view code between your model and controller:
Now if you applied the decorator to your object only “after” the controller,
I wouldn’t mind (provided said decorator contains view logic only). Sadly, that’s
not the case in the code examples provided by Draper.
The approach presented above has more pitfalls still, and one that isn’t apparent
from the code above is that you’re working on “fully” decorated objects
in the controller. Apart from bringing view logic into your controller, this
also is problematic with another feature of Draper which allows to white- or
blacklist functions of the decorated object. Great feature, you decide to blacklist
write operations to your object, including save, but that means for “write” actions
(create and update) you can’t use the decorated object in your controller logic.
No big deal, you just use the plain object and decorate only if the operation
fails and you have to present the user with the form for the object (this would
be the right way to apply view decorators, by the way). Now for whatever reason,
for example for access control, you stick a method into your decorator (it’s
only of interest to instances of that particular class but isn’t business logic,
so you don’t put it in the helper nor in the object but into the decorator) and
now need the decorated object before you call save on it. You now have to juggle
a decorated and an undecorated instance of the object at the same time. Bummer.
Let’s recap what bothers us with the Rails helpers and what Draper can do for
us. Does it avoid cross-helper method name collisions? Sure. Is it “more OOP”?
You’re explicitly calling your helper methods on an object rather than including
a misnamed hodgepodge of methods to be able to call them in views, so let’s
say yes here too. Does it take this jumbled together mess out of the helpers?
It does, and sticks this same mess but with better names into an object. I don’t
consider a namespaced mess better than a non-namespaced one, so this is a draw.
Does it keep view logic out of your controllers? Nope, I’d even say it makes
things worse. Does it keep view logic out of your models? Yeah, but so do helpers.
Does Draper give us more than a buzzword we can add to the list of “OOP things”
our code does? I don’t think so, and you probably shouldn’t either.
How can the Rails helper situation be improved? I’m not sure I have a good answer
to that, but if you think your helpers are too bloated, try splitting them
into smaller topical modules. If you think your helper methods should really
be methods on your business objects but don’t want to litter your model definitions
with view logic or include the ActionView helpers in them (and you shouldn’t!),
then by all means use decorators, but don’t use them as yet another dumping ground!
Feel free to use more than one decorator on business object instances, for example
a TwitterUser, a GooglePlusUser and a XingUser (yeah, decorators don’t need
to be called SomeDecorator). Sure, this results in a call akin to
TwitterUser.new(GooglePlusUser.new(XingUser.new(@user))), but at least it is
very clear what each decorator does and it makes it easier to swap one for another
or refactor any of them. Make also sure to know which decorator belongs to which
MVC step, you can use decorated objects in your controller logic, but decorate
your objects with view logic only at the end of or after your controller logic!
Sure, that’s not as easy just dumping everything into the helpers or into Draper
decorators (I know you can apply multiple Draper decorators on an object and thus
avoid bloating them, the code examples and the fact that the decorated objects
seem to get used in controller logic doesn’t indicate that this was the authors
primary intentions. Furthermore, FooDecorator.find doesn’t make sense for a
“proper”/reusable decorator), but no one ever said programming was easy :–)
I’m at that point again. Relaunching the blog. New theme, new engine, hopefully more content, probably more technical content, probably more english than german, new address. More of a fresh start with imported history than a continuation really.
Blogging didn’t really work for me in the past. I don’t know if it was because of the engine (wordpress), because I didn’t think I have enough interesting things to share, or that the idea-to-blog hurdle is higher than just ranting on twitter (I still do that, by the way…), but I tried twice in the past and it didn’t stick.
So what to expect here? As I said, the content will probably become more technical, the main topics will probably be:
ChiliProject (who woulda thought?),
Rants and discussions on Rails, Ruby and everything around it in general,
Maybe some things about conferences I attend (and maybe later speak at),
Some rare posts about being one of two remote employees in an otherwise one-office software development shop.
A last word of caution: this site still has some rough edges, no comments, no RSS feeds for categories, and so on. I decided to “relaunch” anyway as I have completed importing and converting posts from my previous (wordpress) blog more than 6 weeks ago and haven’t found the time to take care of the few itches I still want to scratch. 80% there is still better than not there at all :-)
Weil es schon spät ist fasse ich mich kurz: Die Aufführung hat der Operntruppe und dem Orchester Riesenspaß gemacht, und von dem vielen Applaus schließe ich, dass es dem Publikum genauso ergangen ist :-)
Update (25.06.2009 19:30): Hier noch ein paar mehr Impressionen der Aufführung, erstens bei den Ruhrnachrichten, und zweitens vor Ort von einem Kommilitonen gefilmt :-)
Da es schon spät ist und morgen heute Abend Erstaufführung ist werde ich mich kurz fassen. Letzten Donnerstag haben wir im Rahmen der Veranstaltungsreihe “Physik zwischen Brötchen und Borussia” nach dem Vortrag ”die Innensaite des Klangkörpers” eine konzertante Aufführung (also ohne Schauspiel) der Oper gegeben. Trotz der schwierigen Bedingungen (Durchzug, kaum Blickkontakt zum Dirigenten, nicht für ein Konzert ausgelegter Saal, …) hat es recht gut geklappt, und der (leider nur) halbvolle Hörsaal hat uns 3 Mal wieder reingerufen. Heute Abend war die Generalprobe, und obwohl sie recht lang gedauert hat, bin ich für die Aufführungen Mittwoch und Samstag sehr zuversichtlich. Der WDR hat uns dabei auch besucht, und live in der Sendung Lokalzeit gesendet, das Ergebnis könnt ihr hier unten sehen. Mehr Infos zu den Konzerten gab es hier schon vorher bei der Konzertankündigung: Gianni Schicchi, wir freuen uns über jeden Besucher, ein Besuch lohnt sich! :-)
15 Jahre lang konnte ich ihn jeden Tag aus dem Fenster meines Zimmers in Mittenimnichtshausen sehen, den Puy de Dôme. Aktuell kann man ihn auch noch im Fernsehen betrachten, in dieser Werbung von Volvic, gegen 0:12, der große Vilkan im Hintergrund. Der Vulkan im Vordergrund, der kurz darauf “aufgeht”, ist der Puy de Parioux, und auf dem kann man wunderbar wandern gehen. Diese Wanderung kommt jetzt auf meine ToDo-Liste für meinen nächsten Besuch in Frankreich, jawohl! :-)
So, jetzt wo ich auch den digitalen Flyer für die Konzerte des UniOrchesters der TU Dortmund, bei dem unter anderem auch Gianni Schicchi aufgeführt wird, kann ich den auch mit euch teilen :-) Die Konzerte finden wie schon angekündigt an den 24.06. und 27.06. statt, jeweils im Audimax der TU Dortmund und im Konzerthaus Dortmund. In der ersten Hälfte werden Werke von Berio und Monteverdi aufgeführt, und in der zweiten Hälfte spielen und singen wir Gianni Schicchi von Puccini. Karten für das Konzert im Konzerthaus gibt es bei der Internetpräsenz des Selbigen, aus der Seite des Konzertes. Wir freuen uns natürlich alle über zahlreiches Erscheinen :-)
Nachtrag (15.06.09 12:10): Mehr Infos gibt es auch noch auf den Seiten der Fakultat für Kunst- und Sportwissenschaften der TU Dortmund: Italienisches Triptychon im Juni.
Kurz vorweg: Eine Sitzprobe ist eine Probe mit allen musikalisch an einer Oper beteiligten Personen, meistens Orchester samt Dirigent und Sänger, gegebenenfalls auch Chor. Wir, also die Gianni Schicchi “Crew”, hatten also heute unsere erste und leider auch letzte Sitzprobe. Es ist leider aus verschiedenen organisatorischen und persönlichen Gründen früher, öfter oder mit wirklich allen (es gab sowohl im Orchester als auch bei den Sängern leere Stühle) zu proben. Ich hätte mir für diese Oper auch ein paar mehr gemeinsame Proben gewünscht, weil es eine musikalisch sehr anspruchsvolle Oper ist, und sowohl das Orchester als auch die Sänger größtenteils aus “Amateuren” (In dem Sinne, dass nur wenige diese Tätigkeit aktuell lernt oder gar beruflich ausübt) bestehen. Nichtsdestotrotz haben wir versucht aus der heutigen Probe das Beste zu holen, und ich denke, dass es uns gelungen ist!
Musikalisch hat also alles gepasst, oder zumindest gab es keine gravierenden Probleme, die nicht in der nächsten Woche noch beseitigt werden könnten. Mal sehen, wie das wird, wenn wir noch die Szene einbringen! Das wird allerdings erst am 16.06. bei der Generalprobe stattfinden (wer mal in eine Generalprobe reinschauen will kann sicher kommen, wenn nicht zu viele andere die gleiche Idee haben, gegebenenfalls ganz unten auf “Kontakt” klicken und mir eine Mail schreiben), und da wird sicherlich noch einiges schief gehen (bei einer Generalprobe passiert immer etwas).
In der Zwischenzeit möchte ich schon mal ein bisschen Werbung machen, und zwar finden die 2 Aufführungen am 24.06. im Audimax der TU Dortmund und am 27.06. im Konzerthaus Dortmund statt, wer es noch nicht getan hat sollte es sich schnell in seinen Kalender schreiben! :-)
Irgendwie ist heute mal wieder ein Tag mit schlechten Gewissem: Egal was ich mache, ich werde ein schlechtes Gewissen haben… Morgen haben wir mit der Operntruppe unsere erste, und leider auch letzte, Sitzprobe mit dem Orchester, und dafür sollte ich noch etwas üben. Dazu hätte ich heute sogar Zeit, allerdings würden mein Hals und meine Stimme mir das wahrscheinlich nachhalten, weil ich gerade noch etwas erkältet bin, und zusätzlich zur Probe morgen heute noch ein Konzert habe. Ich kann mir also aussuchen mich zu ärgern, weil ich nicht geübt habe, oder weil ich mir für die nächsten paar Tage die Stimme versinge, tolle Wurst :-?