68
The Dark Art of Rails Plugins James Adam reevoo.com

The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

  • Upload
    others

  • View
    0

  • Download
    0

Embed Size (px)

Citation preview

Page 1: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

The Dark Artof Rails Plugins

James Adamreevoo.com

Page 2: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

This could be you!

Photo: http://flickr.com/photos/toddhiestand/197704394/

I’m hacking ur Railz appz!!1!

Page 3: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

Anatomy of a plugin

Photo: http://flickr.com/photos/guccibear2005/206352128/

Page 4: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins
Page 5: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

lib

Page 6: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

lib

• added to the $LOAD_PATH

• Dependencies

• order determined by config.plugins

Page 7: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

init.rb

Page 8: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

init.rb

• evaluated near the end of rails initialization

• evaluated in order of config.plugins

• special variables available

• config, directory, name - see source of Rails::Plugin

Page 9: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

tasks[un]install.rb

testgenerators

Page 10: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

Writing Plugins

Page 11: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

Sharing Code

lib tasks

Page 12: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

Enhancing Rails

Page 13: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins
Page 14: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

Modules

module Friendly def hello "hi from #{self}" endend

Page 15: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

require 'friendly'

class Person include Friendlyend

alice = Person.newalice.hello # => "hi from #<Person:0x27704>"

Page 16: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

require 'friendly'

class Personend

Person.send(:include, Friendly)

alice = Person.newalice.hello # => "hi from #<Person:0x27678>"

Page 17: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

Defining class methods

class Person def self.is_friendly? true endend

Page 18: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

... and in modules?

module Friendly def self.is_friendly? true end def hello "hi from #{self}" endend

Page 19: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

Not quite :(

class Person include Friendlyend

Person.is_friendly? # ~> undefined method `is_friendly?' for Person:Class (NoMethodError)

Page 20: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

It’s all about selfmodule Friendly def self.is_friendly? true endend

Friendly.is_friendly? # => true

Page 21: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

Try this insteadmodule Friendly::ClassMethods def is_friendly? true endend

class Person extend Friendly::ClassMethodsend

Person.is_friendly? # => true

Page 22: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

Mixing in Modules

class Person include AnyModule # adds to class definitionend

class Person extend AnyModule # adds to the object (self)end

Page 23: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

Some other ways:

Person.instance_eval do def greetings "hello via \ instance_eval" endend

Page 24: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

Some other ways:

class << Person def salutations "hello via \ class << Person" end end

Page 25: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

module ActsAsFriendly module ClassMethods def is_friendly? true end end

def hello "hi from #{self}!" endend

ActiveRecord::Base.send( :include, ActsAsFriendly)ActiveRecord::Base.extend( ActsAsFriendly::ClassMethods)

Page 26: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

includedmodule B def self.included(base) puts "B included into #{base}!" endend

class A include Bend# => "B included into A!"

Page 27: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

extendedmodule B def self.extended(base) puts "#{base} extended by B!" endend

class A extend Bend# => "A extended by B!"

Page 28: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

module ActsAsFriendly def self.included(base) base.extend(ClassMethods) end

module ClassMethods def is_friendly? true end end

def hello "hi from #{self}!" endend

ActiveRecord::Base.send(:include, ActsAsFriendly)

Page 29: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

module ActsAsFriendly def self.included(base) base.extend(ClassMethods) end

module ClassMethods def is_friendly? true end end

def hello "hi from #{self}!" endend

ActiveRecord::Base.send(:include, ActsAsFriendly)

Page 30: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

class Account < ActiveRecord::Baseend

Account.is_friendly? # => true

Page 31: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

Showing restraint...

• every subclass gets the methods

• maybe we only want to apply it to particular classes

• particularly if we’re going to change how the class behaves (see later...)

Page 32: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

... using class methods

• Ruby class definitions are code

• So, has_many is a class method

Page 33: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

class Alpha

  puts self

end 

# => Alpha

Self in class definitions

class SomeClass puts selfend # >> SomeClass

Page 34: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

Calling methods

class SomeClass def self.greetings "hello" end puts greetingsend# >> hello

Page 35: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

module AbilityToFly def fly! true end # etc...end

class Person def self.has_powers include AbilityToFly endend

Page 36: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

class Hero < Person has_powersend

class Villain < Personend

clark_kent = Hero.newclark_kent.fly! # => true

lex_luthor = Villain.newlex_luthor.fly! # => NoMethodError

Page 37: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

Villain.has_powerslex.fly! # => true

Page 38: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

module MyPlugin def acts_as_friendly include MyPlugin::ActsAsFriendly end

module ActsAsFriendly def self.included(base) base.extend(ClassMethods) end

module ClassMethods def is_friendly? true end end

def hello "hi from #{self}" end

end # of ActsAsFriendlyend # of MyPlugin

ActiveRecord::Base.extend(MyPlugin)

Page 39: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

module MyPlugin def acts_as_friendly include MyPlugin::ActsAsFriendly end

module ActsAsFriendly def self.included(base) base.extend(ClassMethods) end

module ClassMethods def is_friendly? true end end

def hello "hi from #{self}" end

end # of ActsAsFriendlyend # of MyPlugin

ActiveRecord::Base.extend(MyPlugin)

Page 40: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

module MyPlugin def acts_as_friendly include MyPlugin::ActsAsFriendly end

module ActsAsFriendly def self.included(base) base.extend(ClassMethods) end

module ClassMethods def is_friendly? true end end

def hello "hi from #{self}" end

end # of ActsAsFriendlyend # of MyPlugin

ActiveRecord::Base.extend(MyPlugin)

Page 41: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

class Grouch < ActiveRecord::Baseend

oscar = Grouch.newoscar.hello # => NoMethodError

class Hacker < ActiveRecord::Base acts_as_friendlyend

Hacker.is_friendly? # => truejames = Hacker.newjames.hello # => “hi from #<Hacker:0x123>”

Page 42: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

Changing Behaviour

Page 43: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

acts_as_archivable

• when a record is deleted, save a YAML version. Just in case.

• It’s an odd example, but bear with me.

Page 44: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

Archivable

module Archivable def archive_to_yaml File.open("#{id}.yml", 'w') do |f| f.write self.to_yaml end endend

ActiveRecord::Base.send(:include, Archivable)

Page 45: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

Redefining in the classclass ActiveRecord::Base def destroy # Actually delete the record connection.delete %{ DELETE FROM #{table_name} WHERE id = #{self.id} } # call our new method archive_to_yaml endend

Page 46: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

...it’s evil naughty

• ties our new functionality to ActiveRecord, in this example

• maybe we want to add this to DataMapper? Or Sequel? Or Ambition?

Page 47: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

Redefine via a modulemodule Archivable def archive_to_yaml File.open("#{id}.yml") # ...etc... end

def destroy # redefine destroy! connection.delete %{ DELETE FROM #{table_name} WHERE id = #{self.id} } archive_to_yaml endend

Page 48: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

Redefine via a moduleActiveRecord::Base.send(:include, Archivable)

class Thing < ActiveRecord::Baseend

t = Thing.find(:first)

t.destroy # => no archive created :’(

Page 49: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

Some problems

• We can’t redefine methods in a class by simply including a module

• We don’t want to lose the original method, because often we want to call it as part of our new functionality

• We don’t want to copy the original implementation either

Page 50: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

What we’d like

• add an archive method to AR objects

• destroy should call the archive method

• destroy should not lose its original behaviour

• anything we write should be in a module

• it should be DRY

Page 51: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

alias_methodalias_method :original_destroy, :destroy

def new_destroy original_destroy archive_to_yamlend

alias_method :destroy, :new_destroy

Page 52: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

module Archivable alias_method :original_destroy, :destroy def new_destroy original_destroy archive_to_yaml end

alias_method :destroy, :new_destroyend

# ~> undefined method `destroy' for module `Archivable'

Page 53: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

module Archivable def self.included(base) base.class_eval do alias_method :original_destroy, :destroy alias_method :destroy, :new_destroy end end def archive_to_yaml File.open("#{id}.yml") # ... end def new_destroy original_destroy archive_to_yaml endend

ActiveRecord::Base.send(:include, Archivable)

Page 54: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

class Thing < ActiveRecord::Baseend

t = Thing.find(:first)

t.destroy # => archive created!

Page 55: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

But what about when some other plugin tries

freak with destroy?

Page 56: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

alias_method again

alias_method :destroy_without_archiving, :destroy

def destroy_with_archiving  destroy_without_archiving  # then add our new behaviourend  

alias_method :destroy, :destroy_with_archiving

alias_method :destroy_without_archiving, :destroy

def destroy_with_archiving destroy_without_archiving archive_to_yamlend

alias_method :destroy, :destroy_with_archiving

Page 57: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

alias_method_chain

def destroy_with_archiving destroy_without_archiving archive_to_yamlend

alias_method_chain :destroy, :archiving

Page 58: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

module Archivable def self.included(base) base.class_eval do alias_method_chain :destroy, :archiving end end def archive_to_yaml File.open("#{id}.yml", "w") do |f| f.write self.to_yaml end end def destroy_with_archiving destroy_without_archiving archive_to_yaml endend

ActiveRecord::Base.send(:include, Archivable)

Page 59: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

So adding up everything

• use extend to add class method

• include the new behaviour by including a module when class method is called

• use alias_method_chain to wrap existing method

Page 60: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

module ActsAsArchivable def acts_as_archivable include ActsAsArchivable::Behaviour end module Behaviour def self.included(base) base.class_eval do alias_method_chain :destroy, :archiving end end

def archive_to_yaml File.open("#{id}.yml") # ... end

def destroy_with_archiving destroy_without_archiving archive_to_yaml end endend

ActiveRecord::Base.extend(ActsAsArchivable)

Page 61: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

module ActsAsArchivable def acts_as_archivable include ActsAsArchivable::Behaviour alias_method_chain :destroy, :archiving end module Behaviour def archive_to_yaml File.open("#{id}.yml") # ... end

def destroy_with_archiving destroy_without_archiving archive_to_yaml end endend

ActiveRecord::Base.extend(ActsAsArchivable)

Page 62: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

module ActsAsArchivable def acts_as_archivable include ActsAsArchivable::Behaviour alias_method_chain :destroy, :archiving end module Behaviour def archive_to_yaml File.open("#{id}.yml") # ... end

def destroy_with_archiving destroy_without_archiving archive_to_yaml end endend

ActiveRecord::Base.extend(ActsAsArchivable)

Page 63: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

class Thing < ActiveRecord::Baseend

t1 = Thing.create!t1.destroy # => normal destroy calledThing.count # => 0

class PreciousThing < ActiveRecord::Base acts_as_archivableendt2 = PreciousThing.create!t2.destroyPreciousThing.count # => 0Dir["*.yml"] # => ["1.yml"]

Page 64: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

Plugin

Photo: http://flickr.com/photos/jreed/322057793/

Tips

Page 65: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

Package your code

• ...in a module

• domain name, nickname, quirk

module Lazyatom module ActsAsHasselhoff # ... endend

Tip#1

Page 66: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

Developing plugins

• Dependencies.load_once_paths

• config/environment/development.rb

config.after_initialize do Dependencies.load_once_paths. delete_if do |path| path =~ /vendor\/plugins/ endend

Tip#2

Page 67: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

Gems as plugins

• coming in Rails 2.1 (it’s in r9101)

• add rails/init.rb to your gem

• require “rubygems” in environment.rb

Tip#3

Page 68: The Dark Artjaoo.dk/dl/jaoo-ruby-cph-2008/slides/The Dark Art of Rails Plugins.pdf · init.rb • evaluated near the end of rails initialization • evaluated in order of config.plugins

Thanks!

lazyatom.com/plugins