Slide 1

Slide 1 text

rails engines rails-engines.org James Adam

Slide 2

Slide 2 text

“Hello”

Slide 3

Slide 3 text

a bit of background

Slide 4

Slide 4 text

for many clients we build applications simultaneously

Slide 5

Slide 5 text

common functional aspects

Slide 6

Slide 6 text

User Control Auditing Reporting Job Scheduling Charts & Graphs Data Storage Help Systems Content Management

Slide 7

Slide 7 text

many applications many aspects lots of code ✕ lots of maintenance

Slide 8

Slide 8 text

i am lazy i am a conscientious developer

Slide 9

Slide 9 text

Reuse is overrated

Slide 10

Slide 10 text

Reuse is essential ... it just depends on the context

Slide 11

Slide 11 text

e.g. a simple help system

Slide 12

Slide 12 text

db/migrate/001_add_help.rb class AddHelp < ActiveRecord::Migration def self.up create_table :help_pages do |t| t.column :key, :string t.column :title, :string t.column :content, :text end end def self.down drop_table :help_pages end end

Slide 13

Slide 13 text

models/help_page.rb class HelpPage < ActiveRecord::Base end

Slide 14

Slide 14 text

helpers/help_helper.rb module HelpHelper def help_link(key=nil) key ||= params[:controller] + ‘/’ + params[:action] page = HelpPage.find_by_key(key) unless page.nil? link_to(‘[help]’, {:controller => ‘help’, :action => ‘show’, :id => page}, {:class => ‘help_link’}) end end end

Slide 15

Slide 15 text

and in our application:

MeatSword :: Basket

Please find your basket contents below. <%= help_link %>

<% @cart.items.each do |item| %> <%= render :partial => ‘cart/item’ %> <%= link_to(‘[X]’, :action => ‘remove’, :id => item) %> <%= help_link ‘remove_item’ %> <% end %>

Slide 16

Slide 16 text

public/stylesheets/help.css a.help_link { text-decoration: underline; color: #0F0; font-size: 0.8em; } a.help_link:hover { text-decoration: none; color: #000; background-color: #0F0; }

Slide 17

Slide 17 text

generators

Slide 18

Slide 18 text

rails generators $ script/generate model HelpPage create app/models/help_page.rb create test/fixtures/help_pages.yml create test/unit/help_page_test.rb $ script/generate controller Help create app/controllers/help_controller.rb create app/helpers/help_helper.rb create test/functional/... # and so on $ script/generate scaffold HelpPage Help create app/views/help/show.rhtml create app/views/help/edit.rhtml # ... etc generators

Slide 19

Slide 19 text

a package of code templates processed by ERb generators

Slide 20

Slide 20 text

script/generate my_help_system our help generator generators Text create app/models/help_page.rb create app/controllers/help_controller.rb create app/helpers/help_helper.rb create app/views/help/show.rhtml create app/views/help/edit.rhtml create app/views/help/list.rhtml create app/views/help/_form.rhtml create db/migrations/001_add_help.rb create lib/help_system.rb create lib/tasks/help.rake create public/stylesheets/help.css create test/unit/help_test.rb create test/fixtures/help_pages.yml $

Slide 21

Slide 21 text

generators complete subsystem

Slide 22

Slide 22 text

generators share with rubygems

Slide 23

Slide 23 text

meanwhile, in our app: class HelpPage < ActiveRecord::Base # only words containing the # letter ‘x’ are important def summarize(limit=20) content.split.select { |word| word.include?(’x’) }.flatten[0..limit].join end end

Slide 24

Slide 24 text

generators difficult to maintain

Slide 25

Slide 25 text

plugins

Slide 26

Slide 26 text

plugins init.rb start-up

Slide 27

Slide 27 text

plugins install.rb post-install

Slide 28

Slide 28 text

plugins lib/ added to $LOAD_PATH

Slide 29

Slide 29 text

plugins shareable

Slide 30

Slide 30 text

sharing with svn:externals plugins

Slide 31

Slide 31 text

$ svn propset svn:externals \ ‘my_plugin svn://server/my_plugin’ \ vendor/plugins property 'svn:externals' set

Slide 32

Slide 32 text

No content

Slide 33

Slide 33 text

$ svn update vendor/plugins A vendor/plugins/my_plugin/monkey.rb

Slide 34

Slide 34 text

monkey.rb monkey.rb monkey.rb

Slide 35

Slide 35 text

plugins maintainable

Slide 36

Slide 36 text

help plugin help.rb help_helper.rb help_controller.rb show.rhtml help.css 001_add_help.rb

Slide 37

Slide 37 text

plugins only code

Slide 38

Slide 38 text

engines

Slide 39

Slide 39 text

a login system?

Slide 40

Slide 40 text

huge, monolithic, apocalyptic high-level components?

Slide 41

Slide 41 text

easy way to annoy DHH?

Slide 42

Slide 42 text

plugins.succ

Slide 43

Slide 43 text

plugins + 1

Slide 44

Slide 44 text

plugins.succ (plus a little bit more that we found REALLY useful)

Slide 45

Slide 45 text

a mechanism for sharing MVC ‘slices’ between your apps

Slide 46

Slide 46 text

class ArnoldController < ApplicationController def terminator @u = User.find_by_name(’Sarah Conner’) @u.destroy end def total_recall @quote = 'Get your ass to Mars!' render :text => @quote end def twins render :partial => ‘de_vito’, :locals => { :julius => User.find end def sixth_day User.find(:first).clone end end ruby code public assets <% for member in fellowship do %> <%= member.name %> <%= member.gift_from_galadrial <%= member.ringbearer? %> <% end %>

New member?

<%= form_tag :action => ‘add_dude’, :m <%= text_field :new_guy, :species %> <%= text_area :new_guy, :biography % <%= check_box :new_guy, :pawn_of_sau <%= end_form_tag %>
views, partials class JazzMigration < ActiveRecord::Mi def self.up create_table :instruments do |t| t.column :name, :string t.column :type_id, :integer t.column :family, :string t.column :range, :integer, :defa t.column :position_id, :integer, end Instrument.create_default_instrume JazzPlayers.connect_to_instruments end def self.down JazzPlayers.disconnect_from_instru drop_table :instruments end database migrations

Slide 47

Slide 47 text

intuitive layout

Slide 48

Slide 48 text

control your environment Engines.start :help, :reporting, :user_basics, :user_interface

Slide 49

Slide 49 text

shared public assets <%= engine_stylesheet :help %> <%= engine_javascript :user_control %> MeatSword.com

MeatSword :: Meat beyond Meat.

Slide 50

Slide 50 text

migrations rake db:migrate:engines $ Migrated help Migrated meat_sword Migrated south

Slide 51

Slide 51 text

... or just use them like plugins

Slide 52

Slide 52 text

developing engines

Slide 53

Slide 53 text

....guess where the files go

Slide 54

Slide 54 text

init.rb init_engine.rb

Slide 55

Slide 55 text

generating an engine $ script/generate engine Help Author's name: James Adam Author's email: james.adam@gmail.com We can automatically generate a license for you: 0) MIT 1) GPL 2) LGPL 3) None Please select a license: 0 create vendor/plugins/help create vendor/plugins/help/README create vendor/plugins/help/install.rb create vendor/plugins/help/init_engine.rb create vendor/plugins/help/app create vendor/plugins/help/app/models create vendor/plugins/help/app/controllers create vendor/plugins/help/app/helpers create vendor/plugins/help/app/views create vendor/plugins/help/db

Slide 56

Slide 56 text

client customisation module HelpHelper def help_link(key=nil) # overrides method in engine key ||= params[:controller] + ‘/’ + params[:action] page = HelpPage.find_by_key(key) if page.nil? link_to(’Add help page?’, {:controller => ‘help’, :action => ‘create’, :key => key}) else link_to(‘More information...’, # different text {:controller => ‘help’, :action => ‘show’, :id => page}, {:class => ‘info_link’}) end end end /app/helpers/help_helper.rb

Slide 57

Slide 57 text

extending & overriding class HelpController < ApplicationController def create # method NOT in engine if request.post? page = HelpPage.new(params[:new_page]) unless page.save flash[:message] = ‘Oh noes!’ end end end end /app/controllers/help_controller.rb

Slide 58

Slide 58 text

/app/views/help/show.rhtml overriding views

NameOfThisParticularClient.com

Help » <%= @page.title %>

<%= render :partial => ‘index_links’ %>
<%= @page.content %>

Slide 59

Slide 59 text

WARNING: INCOMING CUSS-WORD WARNING: INCOMING CUSS-WORD

Slide 60

Slide 60 text

WHAT THE HELL IS THIS BLACK MAGIC VOODOO?

Slide 61

Slide 61 text

a set of small extensions to Rails http://svn.rails-engines.org/plugins/engines/

Slide 62

Slide 62 text

dependencies_extensions.rb overriding code

Slide 63

Slide 63 text

action_view_extensions.rb action_mailer_extensions.rb overriding views

Slide 64

Slide 64 text

action_view_extensions.rb public assets

Slide 65

Slide 65 text

migration_extensions.rb migrations in plugins

Slide 66

Slide 66 text

testing_extensions.rb flexible fixtures

Slide 67

Slide 67 text

ruby_extensions.rb cheap configuration

Slide 68

Slide 68 text

engines.rb plugin management

Slide 69

Slide 69 text

engines are a mechanism for sharing maintainable code between your apps

Slide 70

Slide 70 text

where from here?

Slide 71

Slide 71 text

bundles <%= require_bundle :help %> MeatSword.org

More meat than you can shake a stick at.

Slide 72

Slide 72 text

happy coexistence with Rails Core

Slide 73

Slide 73 text

feeding back to plugin system

Slide 74

Slide 74 text

opinionated open source

Slide 75

Slide 75 text

rails engines rails-engines.org James Adam dev.rails-engines.org www.rails-engines.org api.rails-engines.org issues/patches: propaganda: docs: