There was a time, when I shared a blog. This post was written by Stephan.
See all blogpost from him or stalk him on github.
Die neuste Version von RefineryCMS (0.9.8.5) nutzt die Rack-Anwendung "Dragonfly", um u.a. den Upload von Bildern zu realisieren. Diese Umstellung hat bei der Pluginerstellung zu einigen Änderungen geführt, die ich hier zusammenfassen möchte.
Als Grundlage soll uns folgendes Szenario dienen:
Mit dem neuen Refinery-Generator "refinery_engine" erzeugen wir ein neues Plugin (seit Umstieg auf Rails 3 auch "Engine" genannt). Gleichzeitig legen wir die für das Projekt-Plugin benötigten Felder an. Ich beschränke mich hier auf ein Titel- und Beschreibungsfeld.
cd /my/path/to_rails/app
rails generate refinery_engine project title:string description:text
Das Plugin sollte nun im Backend von RefineryCMS verfügbar sein.
Wollen wir nun einen Bildupload zur Verfügung stellen, müssen wir zunächst ein neues Feld in unserer Projekttabelle anlegen.
Wir erstellen eine neue Migration,die das neue Feld "project_image" in die Projekttabelle hinzufügt:
Hier der Befehl für den Generator
rails generate migration AddProjectImageToProjects project_image:integer
und die erhaltene Migrationsdatei:
class AddProjectImageToProjects < ActiveRecord::Migration
def self.up
add_column :projects, :project_image, :integer
end
def self.down
remove_column :projects, :project_image
end
end
Es ist aber auch möglich, bei der Erzeugung des Plugins gleich das "Uploadfeld" mit anzugeben:
cd /my/path/to_rails/app
rails generate refinery_engine project title:string description:text project_image:integer
Im neu erstellten Feld wird später die ID gespeichert, die auf das gepsiecherte Bild in der Refinery Image Tabelle verweist. Damit dies funktioniert, muss in unser Projekt-Model noch folgendes eingetragen werden:
class Project < ActiveRecord::Base
validates :title, :presence=> true
#Verknüpfung mit Bildtabelle von RefineryCMS
belongs_to :image, :foreign_key=> "project_image"
end
Merken: Der Foreign-Key kann nur weggelassen werden, wenn das Uploadfeld, in dem die ID zum Bild gespeichert wird, den Namen imageid hat (siehe Rails Konvention). Also bitte an die foreignkey-Option denken und die Namen stets überprüfen.
Die Verbindung in der Datenbank zwischen dem Bild und Projekt ist nun sichergestellt., aber im automatisch generierten Form muss noch das Uploadfeld für den RefineryCMS-File/Image-Manager eingebunden werden:
<%= form_for [:admin, @project] do |f| -%>
<%= render :partial => "/shared/admin/error_messages", :locals => {
:object => @project,
:include_object_name => true
} %>
<div class='field'>
<%= f.label :title -%>
<%= f.text_field :title -%>
</div>
<div class='field'>
<%= f.label :description -%>
<%= f.text_area :description, :rows => 20, :class => 'wymeditor widest' -%>
</div>
<div class='field'>
<%= f.label :project_image -%>
<%= render :partial => "/shared/admin/image_picker", :locals => {
:f => f,
:field => :project_image,
:image => @project.image,
:toggle_image_display => false
} %>
</div>
<%= render :partial => "/shared/admin/form_actions", :locals => {
:f => f,
:continue_editing => false,
:delete_title => t('admin.projects.project.delete'),
:delete_confirmation => t('shared.admin.delete.message', :title => @project.title)
} %>
<% end -%>
Erklärungen zum Partial:
:field beschreibt den Namen des Feldes, in dem die ID des Uploads gespeichert wird, in unserem Fall ist dies das Feld "projectimage"
:image Bild aus der Image-Tabelle von RefineryCMS, @project.image steht durch die belongsto-Methode in unserem Modell zur Verfügung
Ich hoffe, ich konnte euch damit den RefineryCMS-Umstieg von Rails 2 auf Rails 3 erleichtern. Ich möchte noch anmerken, dass folgender Befehl:
rails generate refinery_engine product title:string description:text image:image brochure:resource
wie er hier beschrieben wird, nicht mehr funktioniert. Durch die Umstellung gibt es keinen Typ Image oder Resource mehr (bei mir erzeugt dieser Generatorbefehl ein Formular mit Integerfeldern für Image und Brochure).
So ist es nun möglich, das ImagePicker-Partial von RefineryCMS wieder zu verwenden. Möchte man jetzt aber ein Plugin schreiben, bei dem es verschiedene Arten von Bildern gibt, ist mir bis jetzt noch keine gute Lösung eingefallen.
Bei einem aktuellen Projekt habe ich ein Panoramamodell, in dem 6 verschiedene Bilder geuploadet werden müssen, die dann zu einem großen Gesamtpanorama zusammengefügt werden. Durch den oben beschriebenen Weg ist es aber nur möglich EIN EINZIGES Bild zu verwenden.
Die ersten Gedanken führten dazu, eine hasmany-Assoziation mit dem Parameter :through zu verwenden, was eine extra Tabelle erfordert, die die Einträge zu der RefineryCMS Image-Tabelle herstellt. So arbeitet zum Beispiel auch die neue Rails 3 Variante vom Portfolio-Plugin (<a href="http://github.com/resolve/refinerycms-portfolio/blob/rails3/app/models/portfolioentry.rb">hier ein Blick auf das Model). Dort können zwar dann viele Bilder hochgeladen werden, aber ich habe noch keine Zuordnung, welches geuploadete Bild zur welcher Position im Panorama gehört (oben,unten,links,rechts usw.).
Natürlich kann ich mir auch in meinem Plugin eine neue Dragonfly-App registrieren, aber dann sind die damit gespeicherten Bilder nicht im Filemanager von Refinery (Iamge Plugin) verfügbar.
Ich muss das auf alle Fälle noch weiter überdenken und weiter schlau machen, aber im alten RefineryCMS ging das irgendwie etwas einfacher.
Aber vielleicht gibt es bald ein Tutorial-Update von den Entwicklern.
Bis zum nächsten mal
Da die englische Standardanleitung ((http://rvm.beginrescueend.com/rvm/install/)) bei mir nicht richtig funktionierte, hier jetzt eine kurze Anleitung dafür.
Man sollte als erstes dafür sorgen, dass alle wichtigen Bibliotheken für das Kompilieren von Ruby vorhanden sind, damit
sudo apt-get install libssl-dev zlib1g-dev libreadline-dev
Danach RVM herunterladen und installieren mit folgendem Befehl:
bash < <( curl http://rvm.beginrescueend.com/releases/rvm-install-head )
Dann folgende Zeile am Ende deiner .bashrc einfügen. ((http://web2linux.com/installing-rails-3-on-ubuntu-10-04-lucid-lynx/)) Falls die Datei nicht existiert, einfach in deinem Homeverzeichnis anlegen
if [[ -s "$HOME/.rvm/scripts/rvm" ]] ; then source "$HOME/.rvm/scripts/rvm" ; fi
Jetzt in einer neu geöffneten Konsole eine beliebige Ruby Version installieren.
Danach noch mit
eine Standardversion festlegen und nun sollte in jedem neu geöffneten Terminal Ruby zur Verfügung stehen.