SlideShare a Scribd company logo
Plugins
James Adam
Rails
$ script/plugin install
lib
init.rb
tasks install.rb
uninstall.rb test
Plugins
developing
Rails plugins
can add
anything
Rails plugins
can change
anything
Rails plugins
can do
anything
Methods
Adding
with Ruby, and Rails
Modules
module MineNotYours
def copyright
"(c) me"
end
end
Adding methods to instances...
class SomeClass
include MineNotYours
end
c = SomeClass.new
c.copyright # => "(c) me"
... and so to Models
class SomeModel < AR::Base
include MineNotYours
end
m = SomeModel.find(:first)
m.copyright # => "(c) me"
Adding methods to all models
# Re-opening the target class
# directly
class ActiveRecord::Base
include MineNotYours
end
Adding methods to all models
# Send the ‘include’ message to
# our target class
AR::Base.send(:include, MineNotYours)
Behaviour
Adding
as a part of Class Definitions
Plain Ol’ Ruby Objects
class ConferenceDelegate
attr_accessor :name
end
c = ConferenceDelegate.new
c.name = "Joe Blogs"
c.name # => "Joe Blogs"
Plain Ol’ Ruby Objects
class ConferenceDelegate
:name
end
c = ConferenceDelegate.new
c.name = "Joe Blogs"
c.name # => "Joe Blogs"
attr_accessor
“Class” methods
irb:> c.class.private_methods
=> ["abort", "alias_method", "at_exit", "attr",
"attr_accessor", "attr_reader", "attr_writer",
"binding", "block_given?", "define_method",
"eval", "exec", "exit", "extended", "fail",
"fork", "getc", "gets", "global_variables",
"include", "included", "irb_binding", "lambda",
"load", "local_variables", "private", "proc",
"protected", "public", "puts", "raise",
"remove_class_variable", "remove_const",
"remove_instance_variable", "remove_method",
"require", "sleep", "split", "sprintf", "srand",
"sub", "sub!", "syscall", "system", "test",
"throw", "undef_method", "untrace_var", "warn"]
Ruby Hacker; Know Thy-self
class ConferenceDelegate
attr_accessor :name
end
# self == ConferenceDelegate
Ruby Hacker; Know Thy-self
class ConferenceDelegate
def self.do_something
“OK”
end
do_something
end
# => “OK”
Ruby Hacker; Know Thy-self
class ConferenceDelegate
def self.has_name
attr_accessor :name
end
has_name
end
t = ConferenceDelegate.new
t.name = “Joe Blogs”
Another module
module Personable
def has_person_attributes
attr_accessor :first_name
attr_accessor :last_name
end
end
Adding “class” methods
class RubyGuru
extend Personable
end
has_person_attributes
g = RubyGuru.new
g.first_name = “Dave”
g.last_name = “Thomas”
Specifying Behaviour in Rails
class SuperModel < ActiveRecord::Base
validates_presence_of :rich_boyfriend
validates_size_of :entourage,
:minimum => 20
has_many :vices, :through => :boyfriends
end
class FootballersWife < ActiveRecord::Base
validates_presence_of :rich_boyfriend
validates_size_of :entourage,
:minimum => 5
has_many :vices, :through => :boyfriends
end
Bundling behaviour
module ModelValidation
def acts_as_glamourous(size)
validates_presence_of :rich_boyfriend
validates_size_of :entourage,
:minimum => size
has_many :vices, :through => :boyfriends
end
end
# ... add this method to the target class
ActiveRecord::Base.send(:extend,
ModelValidation)
Our own ActiveRecord behaviour
class Celebrity < AR::Base
acts_as_glamourous(50)
end
Class and instance behaviour
module GlamourPlugin
def acts_as_glamourous(size)
validates_presence_of :rich_boyfriend
# etc...
end
end
Class and instance behaviour
module GlamourPlugin
def acts_as_glamourous
validates_presence_of :rich_boyfriend
# etc...
end
module InstanceBehaviour
def react_to(other_person)
if other_person.is_a?(Paparazzo)
other_person.destroy
end
end
end
end
Class and instance behaviour
module GlamourPlugin
def acts_as_glamourous
validates_presence_of :rich_boyfriend
# etc...
include GlamourPlugin::InstanceBehaviour
end
module InstanceBehaviour
def react_to(other_person)
if other_person.is_a?(Paparazzo)
other_person.destroy
end
end
end
end
Our plugin in action
class Diva < ActiveRecord::Base
acts_as_glamourous
end
dude = Paparazzo.create(:lens => "Huge")
Paparazzo.count # => 1
starlet = Diva.new(:name => "Britney",
:entourage => 873,
:quirk => "No hair")
starlet.react_to(dude)
Paparazzo.count # => 0
RailsPatching
Rails
RailsPatching
Rails
HACKING
changing the behaviour
of existing classes
Changing existing behaviour
# replacing implementation
# via inheritance
class Thing < Object
def object_id
@my_custom_value
end
end
Inheritance is not
always possible
ActiveRecord::Base
ActionController::Base
ActionView::Base
Dependencies ActionMailer::Base
Routing
DispatchingAssociations
... and more...
changing the
implementation of
existing methods
Ruby classes are always open
class ActiveRecord::Base
def count
execute("SELECT COUNT(*)
FROM #{table_name}") / 2
end
end
Aliasing methods
class ActiveRecord::Base
end
alias_method :__count, :count
def count
__count / 2
end
Method chains with Rails
class FunkyBass
def play_it
"Funky"
end
end
bass = FunkyBass.new
bass.play_it # => "Funky"
Method chains - new behaviour
module Soul
def play_it_with_soul
"Smooth & " +
play_it_without_soul
end
end
How alias_method_chain works
class FunkyBass
include Soul
alias_method_chain :play_it, :soul
end
alias_method :play_it_without_soul,
:play_it
alias_method :play_it,
:play_it_with_soul
# underneath the hood:
Adding the new functionality
class FunkyBass
include Soul
alias_method_chain :play_it,
:soul
end
bass.play_it
# => "Smooth & Funky"
Method chains in action
class ActiveRecord::Base
def count_with_fixes
return count_without_fixes + 1
end
alias_method_chain :count, :fixes
end
MyModel.count # calls new method
Patching Rails’ Dependencies
class Dependencies
def require_or_load(file_name)
# load the file from the normal
# places, i.e. $LOAD_PATH
end
end
New plugin-loading behaviour
module LoadingFromPlugins
# we want to replace Rails’ default loading
# behaviour with this
def require_or_load_with_plugins(file_name)
if file_exists_in_plugin(file_name)
load_file_from_plugin(file_name)
else
require_or_load_without_plugins(file_name)
end
end
end
Injecting the new behaviour
module LoadingFromPlugins
def require_or_load_with_plugins(file_name)
if file_exists_in_plugins(file_name)
load_file_from_plugin(file_name)
else
require_or_load_without_plugins(file_name)
end
end
end
def self.included(base)
base.send(:alias_method_chain,
:require_or_load, :plugins)
end
Dependencies.send(:include, LoadingFromPlugins)

More Related Content

Similar to Extending Rails with Plugins (2007)

SOLID Ruby, SOLID Rails
SOLID Ruby, SOLID RailsSOLID Ruby, SOLID Rails
SOLID Ruby, SOLID Rails
Jens-Christian Fischer
 
Ruby Metaprogramming
Ruby MetaprogrammingRuby Metaprogramming
Ruby Metaprogramming
Nando Vieira
 
Say Goodbye to Procedural Programming - Nick Sutterer
Say Goodbye to Procedural Programming - Nick SuttererSay Goodbye to Procedural Programming - Nick Sutterer
Say Goodbye to Procedural Programming - Nick Sutterer
Ruby Meditation
 
Model of the colossus @ Rupy Brazil 2013
Model of the colossus @ Rupy Brazil 2013 Model of the colossus @ Rupy Brazil 2013
Model of the colossus @ Rupy Brazil 2013
Mauro George
 
Working Effectively With Legacy Code
Working Effectively With Legacy CodeWorking Effectively With Legacy Code
Working Effectively With Legacy Code
Naresh Jain
 
Lightning talk
Lightning talkLightning talk
Lightning talk
npalaniuk
 
Ruby: Beyond the Basics
Ruby: Beyond the BasicsRuby: Beyond the Basics
Ruby: Beyond the Basics
Michael Koby
 
Metaprogramovanie #1
Metaprogramovanie #1Metaprogramovanie #1
Metaprogramovanie #1
Jano Suchal
 
Ruby on Rails at PROMPT ISEL '11
Ruby on Rails at PROMPT ISEL '11Ruby on Rails at PROMPT ISEL '11
Ruby on Rails at PROMPT ISEL '11
Pedro Cunha
 
Dsl
DslDsl
Dsl
phoet
 
Intro to Ruby - Twin Cities Code Camp 7
Intro to Ruby - Twin Cities Code Camp 7Intro to Ruby - Twin Cities Code Camp 7
Intro to Ruby - Twin Cities Code Camp 7
Brian Hogan
 
Django Vs Rails
Django Vs RailsDjango Vs Rails
Django Vs Rails
Sérgio Santos
 
Ruby on rails delegate
Ruby on rails delegateRuby on rails delegate
Ruby on rails delegate
Jyaasa Technologies
 
OSDC 2009 Rails Turtorial
OSDC 2009 Rails TurtorialOSDC 2009 Rails Turtorial
OSDC 2009 Rails Turtorial
Yi-Ting Cheng
 
WordPress plugin #2
WordPress plugin #2WordPress plugin #2
WordPress plugin #2
giwoolee
 
The Ring programming language version 1.3 book - Part 30 of 88
The Ring programming language version 1.3 book - Part 30 of 88The Ring programming language version 1.3 book - Part 30 of 88
The Ring programming language version 1.3 book - Part 30 of 88
Mahmoud Samir Fayed
 
Module Magic
Module MagicModule Magic
Module Magic
James Gray
 
Perl Teach-In (part 2)
Perl Teach-In (part 2)Perl Teach-In (part 2)
Perl Teach-In (part 2)
Dave Cross
 
Template rendering in rails
Template rendering in rails Template rendering in rails
Template rendering in rails
Hung Wu Lo
 
PHP OOP Lecture - 02.pptx
PHP OOP Lecture - 02.pptxPHP OOP Lecture - 02.pptx
PHP OOP Lecture - 02.pptx
Atikur Rahman
 

Similar to Extending Rails with Plugins (2007) (20)

SOLID Ruby, SOLID Rails
SOLID Ruby, SOLID RailsSOLID Ruby, SOLID Rails
SOLID Ruby, SOLID Rails
 
Ruby Metaprogramming
Ruby MetaprogrammingRuby Metaprogramming
Ruby Metaprogramming
 
Say Goodbye to Procedural Programming - Nick Sutterer
Say Goodbye to Procedural Programming - Nick SuttererSay Goodbye to Procedural Programming - Nick Sutterer
Say Goodbye to Procedural Programming - Nick Sutterer
 
Model of the colossus @ Rupy Brazil 2013
Model of the colossus @ Rupy Brazil 2013 Model of the colossus @ Rupy Brazil 2013
Model of the colossus @ Rupy Brazil 2013
 
Working Effectively With Legacy Code
Working Effectively With Legacy CodeWorking Effectively With Legacy Code
Working Effectively With Legacy Code
 
Lightning talk
Lightning talkLightning talk
Lightning talk
 
Ruby: Beyond the Basics
Ruby: Beyond the BasicsRuby: Beyond the Basics
Ruby: Beyond the Basics
 
Metaprogramovanie #1
Metaprogramovanie #1Metaprogramovanie #1
Metaprogramovanie #1
 
Ruby on Rails at PROMPT ISEL '11
Ruby on Rails at PROMPT ISEL '11Ruby on Rails at PROMPT ISEL '11
Ruby on Rails at PROMPT ISEL '11
 
Dsl
DslDsl
Dsl
 
Intro to Ruby - Twin Cities Code Camp 7
Intro to Ruby - Twin Cities Code Camp 7Intro to Ruby - Twin Cities Code Camp 7
Intro to Ruby - Twin Cities Code Camp 7
 
Django Vs Rails
Django Vs RailsDjango Vs Rails
Django Vs Rails
 
Ruby on rails delegate
Ruby on rails delegateRuby on rails delegate
Ruby on rails delegate
 
OSDC 2009 Rails Turtorial
OSDC 2009 Rails TurtorialOSDC 2009 Rails Turtorial
OSDC 2009 Rails Turtorial
 
WordPress plugin #2
WordPress plugin #2WordPress plugin #2
WordPress plugin #2
 
The Ring programming language version 1.3 book - Part 30 of 88
The Ring programming language version 1.3 book - Part 30 of 88The Ring programming language version 1.3 book - Part 30 of 88
The Ring programming language version 1.3 book - Part 30 of 88
 
Module Magic
Module MagicModule Magic
Module Magic
 
Perl Teach-In (part 2)
Perl Teach-In (part 2)Perl Teach-In (part 2)
Perl Teach-In (part 2)
 
Template rendering in rails
Template rendering in rails Template rendering in rails
Template rendering in rails
 
PHP OOP Lecture - 02.pptx
PHP OOP Lecture - 02.pptxPHP OOP Lecture - 02.pptx
PHP OOP Lecture - 02.pptx
 

More from lazyatom

Engines: Team Development on Rails (2005)
Engines: Team Development on Rails (2005)Engines: Team Development on Rails (2005)
Engines: Team Development on Rails (2005)
lazyatom
 
The Even Darker Art of Rails Engines (2009)
The Even Darker Art of Rails Engines (2009)The Even Darker Art of Rails Engines (2009)
The Even Darker Art of Rails Engines (2009)
lazyatom
 
Gem That (2009)
Gem That (2009)Gem That (2009)
Gem That (2009)
lazyatom
 
Do we need more test frameworks? (2011)
Do we need more test frameworks? (2011)Do we need more test frameworks? (2011)
Do we need more test frameworks? (2011)
lazyatom
 
IoT Printer (2012)
IoT Printer (2012)IoT Printer (2012)
IoT Printer (2012)
lazyatom
 
The Even Darker Art Of Rails Engines
The Even Darker Art Of Rails EnginesThe Even Darker Art Of Rails Engines
The Even Darker Art Of Rails Engines
lazyatom
 

More from lazyatom (6)

Engines: Team Development on Rails (2005)
Engines: Team Development on Rails (2005)Engines: Team Development on Rails (2005)
Engines: Team Development on Rails (2005)
 
The Even Darker Art of Rails Engines (2009)
The Even Darker Art of Rails Engines (2009)The Even Darker Art of Rails Engines (2009)
The Even Darker Art of Rails Engines (2009)
 
Gem That (2009)
Gem That (2009)Gem That (2009)
Gem That (2009)
 
Do we need more test frameworks? (2011)
Do we need more test frameworks? (2011)Do we need more test frameworks? (2011)
Do we need more test frameworks? (2011)
 
IoT Printer (2012)
IoT Printer (2012)IoT Printer (2012)
IoT Printer (2012)
 
The Even Darker Art Of Rails Engines
The Even Darker Art Of Rails EnginesThe Even Darker Art Of Rails Engines
The Even Darker Art Of Rails Engines
 

Recently uploaded

一比一原版(sdsu毕业证书)圣地亚哥州立大学毕业证如何办理
一比一原版(sdsu毕业证书)圣地亚哥州立大学毕业证如何办理一比一原版(sdsu毕业证书)圣地亚哥州立大学毕业证如何办理
一比一原版(sdsu毕业证书)圣地亚哥州立大学毕业证如何办理
kgyxske
 
Top Benefits of Using Salesforce Healthcare CRM for Patient Management.pdf
Top Benefits of Using Salesforce Healthcare CRM for Patient Management.pdfTop Benefits of Using Salesforce Healthcare CRM for Patient Management.pdf
Top Benefits of Using Salesforce Healthcare CRM for Patient Management.pdf
VALiNTRY360
 
All you need to know about Spring Boot and GraalVM
All you need to know about Spring Boot and GraalVMAll you need to know about Spring Boot and GraalVM
All you need to know about Spring Boot and GraalVM
Alina Yurenko
 
WWDC 2024 Keynote Review: For CocoaCoders Austin
WWDC 2024 Keynote Review: For CocoaCoders AustinWWDC 2024 Keynote Review: For CocoaCoders Austin
WWDC 2024 Keynote Review: For CocoaCoders Austin
Patrick Weigel
 
Preparing Non - Technical Founders for Engaging a Tech Agency
Preparing Non - Technical Founders for Engaging  a  Tech AgencyPreparing Non - Technical Founders for Engaging  a  Tech Agency
Preparing Non - Technical Founders for Engaging a Tech Agency
ISH Technologies
 
A Comprehensive Guide on Implementing Real-World Mobile Testing Strategies fo...
A Comprehensive Guide on Implementing Real-World Mobile Testing Strategies fo...A Comprehensive Guide on Implementing Real-World Mobile Testing Strategies fo...
A Comprehensive Guide on Implementing Real-World Mobile Testing Strategies fo...
kalichargn70th171
 
ALGIT - Assembly Line for Green IT - Numbers, Data, Facts
ALGIT - Assembly Line for Green IT - Numbers, Data, FactsALGIT - Assembly Line for Green IT - Numbers, Data, Facts
ALGIT - Assembly Line for Green IT - Numbers, Data, Facts
Green Software Development
 
Measures in SQL (SIGMOD 2024, Santiago, Chile)
Measures in SQL (SIGMOD 2024, Santiago, Chile)Measures in SQL (SIGMOD 2024, Santiago, Chile)
Measures in SQL (SIGMOD 2024, Santiago, Chile)
Julian Hyde
 
UI5con 2024 - Bring Your Own Design System
UI5con 2024 - Bring Your Own Design SystemUI5con 2024 - Bring Your Own Design System
UI5con 2024 - Bring Your Own Design System
Peter Muessig
 
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
Paul Brebner
 
Quarter 3 SLRP grade 9.. gshajsbhhaheabh
Quarter 3 SLRP grade 9.. gshajsbhhaheabhQuarter 3 SLRP grade 9.. gshajsbhhaheabh
Quarter 3 SLRP grade 9.. gshajsbhhaheabh
aisafed42
 
J-Spring 2024 - Going serverless with Quarkus, GraalVM native images and AWS ...
J-Spring 2024 - Going serverless with Quarkus, GraalVM native images and AWS ...J-Spring 2024 - Going serverless with Quarkus, GraalVM native images and AWS ...
J-Spring 2024 - Going serverless with Quarkus, GraalVM native images and AWS ...
Bert Jan Schrijver
 
ACE - Team 24 Wrapup event at ahmedabad.
ACE - Team 24 Wrapup event at ahmedabad.ACE - Team 24 Wrapup event at ahmedabad.
ACE - Team 24 Wrapup event at ahmedabad.
Maitrey Patel
 
UI5con 2024 - Boost Your Development Experience with UI5 Tooling Extensions
UI5con 2024 - Boost Your Development Experience with UI5 Tooling ExtensionsUI5con 2024 - Boost Your Development Experience with UI5 Tooling Extensions
UI5con 2024 - Boost Your Development Experience with UI5 Tooling Extensions
Peter Muessig
 
E-commerce Development Services- Hornet Dynamics
E-commerce Development Services- Hornet DynamicsE-commerce Development Services- Hornet Dynamics
E-commerce Development Services- Hornet Dynamics
Hornet Dynamics
 
GreenCode-A-VSCode-Plugin--Dario-Jurisic
GreenCode-A-VSCode-Plugin--Dario-JurisicGreenCode-A-VSCode-Plugin--Dario-Jurisic
GreenCode-A-VSCode-Plugin--Dario-Jurisic
Green Software Development
 
Enums On Steroids - let's look at sealed classes !
Enums On Steroids - let's look at sealed classes !Enums On Steroids - let's look at sealed classes !
Enums On Steroids - let's look at sealed classes !
Marcin Chrost
 
Energy consumption of Database Management - Florina Jonuzi
Energy consumption of Database Management - Florina JonuziEnergy consumption of Database Management - Florina Jonuzi
Energy consumption of Database Management - Florina Jonuzi
Green Software Development
 
Project Management: The Role of Project Dashboards.pdf
Project Management: The Role of Project Dashboards.pdfProject Management: The Role of Project Dashboards.pdf
Project Management: The Role of Project Dashboards.pdf
Karya Keeper
 
Malibou Pitch Deck For Its €3M Seed Round
Malibou Pitch Deck For Its €3M Seed RoundMalibou Pitch Deck For Its €3M Seed Round
Malibou Pitch Deck For Its €3M Seed Round
sjcobrien
 

Recently uploaded (20)

一比一原版(sdsu毕业证书)圣地亚哥州立大学毕业证如何办理
一比一原版(sdsu毕业证书)圣地亚哥州立大学毕业证如何办理一比一原版(sdsu毕业证书)圣地亚哥州立大学毕业证如何办理
一比一原版(sdsu毕业证书)圣地亚哥州立大学毕业证如何办理
 
Top Benefits of Using Salesforce Healthcare CRM for Patient Management.pdf
Top Benefits of Using Salesforce Healthcare CRM for Patient Management.pdfTop Benefits of Using Salesforce Healthcare CRM for Patient Management.pdf
Top Benefits of Using Salesforce Healthcare CRM for Patient Management.pdf
 
All you need to know about Spring Boot and GraalVM
All you need to know about Spring Boot and GraalVMAll you need to know about Spring Boot and GraalVM
All you need to know about Spring Boot and GraalVM
 
WWDC 2024 Keynote Review: For CocoaCoders Austin
WWDC 2024 Keynote Review: For CocoaCoders AustinWWDC 2024 Keynote Review: For CocoaCoders Austin
WWDC 2024 Keynote Review: For CocoaCoders Austin
 
Preparing Non - Technical Founders for Engaging a Tech Agency
Preparing Non - Technical Founders for Engaging  a  Tech AgencyPreparing Non - Technical Founders for Engaging  a  Tech Agency
Preparing Non - Technical Founders for Engaging a Tech Agency
 
A Comprehensive Guide on Implementing Real-World Mobile Testing Strategies fo...
A Comprehensive Guide on Implementing Real-World Mobile Testing Strategies fo...A Comprehensive Guide on Implementing Real-World Mobile Testing Strategies fo...
A Comprehensive Guide on Implementing Real-World Mobile Testing Strategies fo...
 
ALGIT - Assembly Line for Green IT - Numbers, Data, Facts
ALGIT - Assembly Line for Green IT - Numbers, Data, FactsALGIT - Assembly Line for Green IT - Numbers, Data, Facts
ALGIT - Assembly Line for Green IT - Numbers, Data, Facts
 
Measures in SQL (SIGMOD 2024, Santiago, Chile)
Measures in SQL (SIGMOD 2024, Santiago, Chile)Measures in SQL (SIGMOD 2024, Santiago, Chile)
Measures in SQL (SIGMOD 2024, Santiago, Chile)
 
UI5con 2024 - Bring Your Own Design System
UI5con 2024 - Bring Your Own Design SystemUI5con 2024 - Bring Your Own Design System
UI5con 2024 - Bring Your Own Design System
 
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
 
Quarter 3 SLRP grade 9.. gshajsbhhaheabh
Quarter 3 SLRP grade 9.. gshajsbhhaheabhQuarter 3 SLRP grade 9.. gshajsbhhaheabh
Quarter 3 SLRP grade 9.. gshajsbhhaheabh
 
J-Spring 2024 - Going serverless with Quarkus, GraalVM native images and AWS ...
J-Spring 2024 - Going serverless with Quarkus, GraalVM native images and AWS ...J-Spring 2024 - Going serverless with Quarkus, GraalVM native images and AWS ...
J-Spring 2024 - Going serverless with Quarkus, GraalVM native images and AWS ...
 
ACE - Team 24 Wrapup event at ahmedabad.
ACE - Team 24 Wrapup event at ahmedabad.ACE - Team 24 Wrapup event at ahmedabad.
ACE - Team 24 Wrapup event at ahmedabad.
 
UI5con 2024 - Boost Your Development Experience with UI5 Tooling Extensions
UI5con 2024 - Boost Your Development Experience with UI5 Tooling ExtensionsUI5con 2024 - Boost Your Development Experience with UI5 Tooling Extensions
UI5con 2024 - Boost Your Development Experience with UI5 Tooling Extensions
 
E-commerce Development Services- Hornet Dynamics
E-commerce Development Services- Hornet DynamicsE-commerce Development Services- Hornet Dynamics
E-commerce Development Services- Hornet Dynamics
 
GreenCode-A-VSCode-Plugin--Dario-Jurisic
GreenCode-A-VSCode-Plugin--Dario-JurisicGreenCode-A-VSCode-Plugin--Dario-Jurisic
GreenCode-A-VSCode-Plugin--Dario-Jurisic
 
Enums On Steroids - let's look at sealed classes !
Enums On Steroids - let's look at sealed classes !Enums On Steroids - let's look at sealed classes !
Enums On Steroids - let's look at sealed classes !
 
Energy consumption of Database Management - Florina Jonuzi
Energy consumption of Database Management - Florina JonuziEnergy consumption of Database Management - Florina Jonuzi
Energy consumption of Database Management - Florina Jonuzi
 
Project Management: The Role of Project Dashboards.pdf
Project Management: The Role of Project Dashboards.pdfProject Management: The Role of Project Dashboards.pdf
Project Management: The Role of Project Dashboards.pdf
 
Malibou Pitch Deck For Its €3M Seed Round
Malibou Pitch Deck For Its €3M Seed RoundMalibou Pitch Deck For Its €3M Seed Round
Malibou Pitch Deck For Its €3M Seed Round
 

Extending Rails with Plugins (2007)

  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10. lib
  • 19. Adding methods to instances... class SomeClass include MineNotYours end c = SomeClass.new c.copyright # => "(c) me"
  • 20. ... and so to Models class SomeModel < AR::Base include MineNotYours end m = SomeModel.find(:first) m.copyright # => "(c) me"
  • 21. Adding methods to all models # Re-opening the target class # directly class ActiveRecord::Base include MineNotYours end
  • 22. Adding methods to all models # Send the ‘include’ message to # our target class AR::Base.send(:include, MineNotYours)
  • 23.
  • 24. Behaviour Adding as a part of Class Definitions
  • 25. Plain Ol’ Ruby Objects class ConferenceDelegate attr_accessor :name end c = ConferenceDelegate.new c.name = "Joe Blogs" c.name # => "Joe Blogs"
  • 26. Plain Ol’ Ruby Objects class ConferenceDelegate :name end c = ConferenceDelegate.new c.name = "Joe Blogs" c.name # => "Joe Blogs" attr_accessor
  • 27. “Class” methods irb:> c.class.private_methods => ["abort", "alias_method", "at_exit", "attr", "attr_accessor", "attr_reader", "attr_writer", "binding", "block_given?", "define_method", "eval", "exec", "exit", "extended", "fail", "fork", "getc", "gets", "global_variables", "include", "included", "irb_binding", "lambda", "load", "local_variables", "private", "proc", "protected", "public", "puts", "raise", "remove_class_variable", "remove_const", "remove_instance_variable", "remove_method", "require", "sleep", "split", "sprintf", "srand", "sub", "sub!", "syscall", "system", "test", "throw", "undef_method", "untrace_var", "warn"]
  • 28. Ruby Hacker; Know Thy-self class ConferenceDelegate attr_accessor :name end # self == ConferenceDelegate
  • 29. Ruby Hacker; Know Thy-self class ConferenceDelegate def self.do_something “OK” end do_something end # => “OK”
  • 30. Ruby Hacker; Know Thy-self class ConferenceDelegate def self.has_name attr_accessor :name end has_name end t = ConferenceDelegate.new t.name = “Joe Blogs”
  • 31. Another module module Personable def has_person_attributes attr_accessor :first_name attr_accessor :last_name end end
  • 32. Adding “class” methods class RubyGuru extend Personable end has_person_attributes g = RubyGuru.new g.first_name = “Dave” g.last_name = “Thomas”
  • 33. Specifying Behaviour in Rails class SuperModel < ActiveRecord::Base validates_presence_of :rich_boyfriend validates_size_of :entourage, :minimum => 20 has_many :vices, :through => :boyfriends end class FootballersWife < ActiveRecord::Base validates_presence_of :rich_boyfriend validates_size_of :entourage, :minimum => 5 has_many :vices, :through => :boyfriends end
  • 34. Bundling behaviour module ModelValidation def acts_as_glamourous(size) validates_presence_of :rich_boyfriend validates_size_of :entourage, :minimum => size has_many :vices, :through => :boyfriends end end # ... add this method to the target class ActiveRecord::Base.send(:extend, ModelValidation)
  • 35. Our own ActiveRecord behaviour class Celebrity < AR::Base acts_as_glamourous(50) end
  • 36. Class and instance behaviour module GlamourPlugin def acts_as_glamourous(size) validates_presence_of :rich_boyfriend # etc... end end
  • 37. Class and instance behaviour module GlamourPlugin def acts_as_glamourous validates_presence_of :rich_boyfriend # etc... end module InstanceBehaviour def react_to(other_person) if other_person.is_a?(Paparazzo) other_person.destroy end end end end
  • 38. Class and instance behaviour module GlamourPlugin def acts_as_glamourous validates_presence_of :rich_boyfriend # etc... include GlamourPlugin::InstanceBehaviour end module InstanceBehaviour def react_to(other_person) if other_person.is_a?(Paparazzo) other_person.destroy end end end end
  • 39. Our plugin in action class Diva < ActiveRecord::Base acts_as_glamourous end dude = Paparazzo.create(:lens => "Huge") Paparazzo.count # => 1 starlet = Diva.new(:name => "Britney", :entourage => 873, :quirk => "No hair") starlet.react_to(dude) Paparazzo.count # => 0
  • 42. changing the behaviour of existing classes
  • 43. Changing existing behaviour # replacing implementation # via inheritance class Thing < Object def object_id @my_custom_value end end
  • 44. Inheritance is not always possible ActiveRecord::Base ActionController::Base ActionView::Base Dependencies ActionMailer::Base Routing DispatchingAssociations ... and more...
  • 46. Ruby classes are always open class ActiveRecord::Base def count execute("SELECT COUNT(*) FROM #{table_name}") / 2 end end
  • 47. Aliasing methods class ActiveRecord::Base end alias_method :__count, :count def count __count / 2 end
  • 48. Method chains with Rails class FunkyBass def play_it "Funky" end end bass = FunkyBass.new bass.play_it # => "Funky"
  • 49. Method chains - new behaviour module Soul def play_it_with_soul "Smooth & " + play_it_without_soul end end
  • 50. How alias_method_chain works class FunkyBass include Soul alias_method_chain :play_it, :soul end alias_method :play_it_without_soul, :play_it alias_method :play_it, :play_it_with_soul # underneath the hood:
  • 51. Adding the new functionality class FunkyBass include Soul alias_method_chain :play_it, :soul end bass.play_it # => "Smooth & Funky"
  • 52. Method chains in action class ActiveRecord::Base def count_with_fixes return count_without_fixes + 1 end alias_method_chain :count, :fixes end MyModel.count # calls new method
  • 53. Patching Rails’ Dependencies class Dependencies def require_or_load(file_name) # load the file from the normal # places, i.e. $LOAD_PATH end end
  • 54. New plugin-loading behaviour module LoadingFromPlugins # we want to replace Rails’ default loading # behaviour with this def require_or_load_with_plugins(file_name) if file_exists_in_plugin(file_name) load_file_from_plugin(file_name) else require_or_load_without_plugins(file_name) end end end
  • 55. Injecting the new behaviour module LoadingFromPlugins def require_or_load_with_plugins(file_name) if file_exists_in_plugins(file_name) load_file_from_plugin(file_name) else require_or_load_without_plugins(file_name) end end end def self.included(base) base.send(:alias_method_chain, :require_or_load, :plugins) end Dependencies.send(:include, LoadingFromPlugins)