content-driven web applications with magnolia cms and ruby on rails

Post on 19-May-2015

2.543 Views

Category:

Technology

2 Downloads

Preview:

Click to see full reader

DESCRIPTION

Instead of going with a traditional Java-only based stack, Dievision chose to integrate Magnolia CMS with (J)Ruby on Rails and to use Rails as the web development framework for its Magnolia-based sites. In this session, will share some of our experiences with this approach. We will talk about the initial motivation and the differences the environment makes for a developer as well as for a team. You will learn about the practical aspects of the Java/Ruby co-existence, how to integrate Magnolia CMS with the Rails framework and how to work with JCR-based content from a Ruby perspective. Finally, we will cover some options of testing and deploying a site.

TRANSCRIPT

Content-DrivenWeb Applications with

Magnolia and Ruby on Rails

Patrik Metzmacher, Dievisionhttp://www.dievision.de

I’m not really talking aboutRuby or Rails

Creating an environment which

clients enjoy towork with

and

(our) developers loveto develop for.

The Approach

How to run a Rails app within Magnolia

Developing a minimalMagnolia/Rails application

Testing

The Rails Ecosystem

The Approach

Same paradigms for content- and application-driven websites

Clean, consistent MVC architecture

File-based configuration and application data

Work with version control andyour favorite text editors/IDEs

Invent as few wheels as possible

Leverage ready-made web-focussed solutions, best practices and a large development community

CachingDependency Management E-Mails

ORM

Forms

Validation

AJAX

JavaScript

Integration

SecurityMVC

Helpers/

Utilites

Templating

Prototyping

HTML/CSS

Preprocessors

Perfor

mance

Monitor

ingReusable Components

Deployment

Client-side performance optimizationUnit Te

sting

Integration Testing

IDE/Editor support

Scalability

Running Rails within Magnolia

Developers Clients

JCRRepository

Hierarchical NoSQL-Storethat can be edited by

normal people.

JCRRepository

SQLDatabase

100% Java-based Ruby implementation

Mature

Fastest Ruby 1.8.7 implementation

Web apps can be deployed in standard Servlet containers

JRuby Rack Filter

Rack Web Application

Rack Connector

Installation

Rack Filter

Aggregation Filter

Rendering FilterMagnolia Filter Chain

Rails Application

Rails “Base” controller providingcontent, page, state objects

Mapping between Magnolia Templates and Rails Layouts

MyApp::Application.routes.draw do

match "/(*cmspath)" => "sinicum/controllers/base#index"

end

config/routes.rb

<html> <head> <title> <%= cms_out :title %> </title> </head> <body> <%= main_bar %> <h1> <%= cms_out :title %> </h1> <%= edit_bar :dialog => "title_dialog" %> </body></html>

app/views/layouts/homepage.html.erb

Model View Controller

Magnolia Module for JRuby/Rack integration

Magnolia/Rails “Base” Controller

Helpers to match the Taglib

JCR-Wrapper withRuby Semantics

ActiveRecord-like JCR/Object Mapper

File-based configuration

Utilities: Scheduler, Imaging, Testing, etc.

Developing a minimal Magnolia/Rails application

The Task

class Templates::PressRelease include Sinicum::Jcr::Base def title_homepage title_short || title endend

app/models/templates/press_release.rb

class Templates::PressRelease include Sinicum::Jcr::Base def title_homepage title_short || title end def title_short @content[:title_short] end def title @content[:title] end end

app/models/templates/press_release.rb

MyApp::Application.routes.draw do

match "/en" => "home#index" match "/(*cmspath)" => "sinicum/controllers/base#index"

end

config/routes.rb

class HomeController < Sinicum::Controllers::Base def index @releases = Templates::PressRelease.for_homepage cms_render end end

app/controllers/home_controller.rb

<ul> <% @releases.each do |release| -%> <li> <%= link_to release.title_homepage, release %> </li> <% end -%></ul>

app/views/layouts/homepage.html.erb

class Templates::PressRelease include Sinicum::Jcr::Base def self.for_homepage where(:show_on_homepage => true). order("release_date desc", "order_day"). limit(2) end def title_homepage title_short || title end end

app/models/templates/press_release.rb

class Templates::PressRelease include Sinicum::Jcr::Base scope :ordered, order("release_date desc", "order_day") scope :for_homepage, ordered.where(:show_on_homepage => true).limit(2)

def title_homepage title_short || title end end

app/models/templates/press_release.rb

Configuration

Consistent

Editable

Version-Controlable

Tied to the models

<?xml version="1.0" encoding="UTF-8"?><sv:node sv:name="box_picture_teaser_large_item_dialog" xmlns:sv="http://www.jcp.org/jcr/sv/1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <sv:property sv:name="jcr:primaryType" sv:type="Name"> <sv:value>mgnl:contentNode</sv:value> </sv:property> <sv:property sv:name="jcr:mixinTypes" sv:type="Name"> <sv:value>mix:lockable</sv:value> </sv:property> <sv:property sv:name="jcr:uuid" sv:type="String"> <sv:value>92a944c5-c5b3-423c-af93-34a7b948c5be</sv:value> </sv:property> <sv:node sv:name="MetaData"> <sv:property sv:name="jcr:primaryType" sv:type="Name"> <sv:value>mgnl:metaData</sv:value> </sv:property> <sv:property sv:name="mgnl:activated" sv:type="Boolean"> <sv:value>true</sv:value> </sv:property> <sv:property sv:name="mgnl:activatorid" sv:type="String"> <sv:value>username</sv:value> </sv:property> <sv:property sv:name="mgnl:authorid" sv:type="String"> <sv:value>authorname</sv:value> </sv:property>

class CreateProductRegistration < ActiveRecord::Migration def self.up create_table :product_registrations do |t| t.column :first_name, :string t.column :last_name, :string t.column :email, :string t.column :date_of_birth, :date t.column :date_of_purchase, :date t.column :point_of_sale, :string t.column :roles, :string t.column :newsletter_subscription, :boolean end end

def self.down drop_table :product_registrations endend

db/migrate/20100916101243_create_product_registration.rb

video_dialog: height: 500 tab_main:

title: controlType: edit label: Title

video_file: controlType: uuidLink description: Link to the video file repository: dms label: Video

db/jcr/module/dialogs/video_dialog.yml

Testing

<ul> <% @releases.each do |release| -%> <li> <%= link_to release.title_homepage, release %> </li> <% end -%></ul>

app/views/layouts/homepage.html.erb

require 'spec_helper'

describe "layouts/homepage.html.erb" do

it "displays the title of a press release" do render rendered.should contain("Sustainability World Index") end

end

spec/views/layouts/homepage.html.erb_spec.rb

require 'spec_helper'

describe "layouts/homepage.html.erb" do it "displays the title of a press release" do

releases = [Templates::PressRelease.new( :title => "Lorem ipsum Sustainability World Index dolor sit amet", :title_short => "Sustainability World Index" )] assign(:releases, releases)

render rendered.should contain("Sustainability World Index") endend

spec/views/layouts/homepage.html.erb_spec.rb

describe "layouts/homepage.html.erb" do before(:each) do assign(:releases, [Factory(:sustainability_release)]) end it "displays the title of a press release" do render rendered.should contain("Sustainability World Index") endend

spec/views/layouts/homepage.html.erb_spec.rb

Factory.define :sustainability_release, :class => Templates::PressRelease do |r| r.title "Lorem ipsum Sustainability World Index dolor sit amet", r.title_short "Sustainability World Index"end

spec/factories/templates/press_releases.rb

The Ecosystem

What we use

Capistrano for deployment

Haml/Sass for better HTML templates and CSS

NewRelic for performance monitoring

Many high-quality Gems and Plugins

Our Conclusion

Very productive and “scalable” environment

Performance is just fine

Save/Reload vs. Save/Compile/Restart/Reload

You can refactor in a dynamic language

Collaboration is easier when everyone uses the same tools

http://www.dievision.de

top related