The Even-Darker Art of Rails Engines
@lazyatom
github.com/lazyatom/engines
Rails 2.3
history
November 2005
it’s distracting!
reuse is overrated!
Evil! Evil! Evil! Evil! Evil! Evil! Evil! Evil! Shit!
eek!
appable_plugins
desert
merb slices?
engines
!"#$%&!"#$'#(%&$#)&!"#$%&*$+,#-.!) !"#$%&'() $$*%&'()$++,$-'%!.%&'()./0#'12%)/'0 "0! 3$405/0"6$%1"$7-(5/06$8/)9$%0$%77:$!/1";)'1<= !"#$"05/0"> $$9%6.%77.!/1";)'1<> "0! 3$?")(106$)1("$/#$)9"$"05/0"$69/76$8/)9$%$1'()/05$#/-" !"#$1'()"!> $$@/-"="A/6)>B1'()/05.#/-"C "0! !"#$D/"8.7%)9 $$@/-"=E'/0B!/1";)'1<F$G%77GF$GD/"86GC "0!
app/controllers/ models/ helpers/ views/ metal/
*$+,#-&"**&23-'!3$$(!&*$+,#-523-'!3$$(!.!) ;-%66$H-(5/0I'0)1'--"1 /0/1**$#2"'#3-43-'!3$$(! $$!"#$/0!"A $$$$1"0!"1$J)"A)$,K$LM"--'F$H-(5/0NL $$"0! "0!
9"-7"1$J%-- won’t load from your plugin
Ticket #1905
config/routes.rb
*$+,#-&23-6#,&!3+'(%.!) O;)/'0I'0)1'--"1JJ?'()/05JJ?'()"6=!1%8$!'$+2%7+ $$2%7=;'00";)$G:7%)9GF$J;'0)1'--"1$,K$L7-(5/0LF$ $$$$$$$$$$$$$$$$$$$$$$$J%;)/'0$,K$L/0!"AL "0!
top precedence
in your plugin: O;)/'0I'0)1'--"1JJ?'()/05JJ?'()"6=!1%8$!'$+2%7+ $$2%7=;'00";)$G:7%)9GF$J;'0)1'--"1$,K$L7-(5/0LF$ $$$$$$$$$$$$$$$$$$$$$$$J%;)/'0$,K$L/0!"AL "0! in your app: O;)/'0I'0)1'--"1JJ?'()/05JJ?'()"6=!1%8$!'$+2%7+ $$3$===$')9"1$1'()"6$=== $$2%7=;'00";)$G:7%)9GF$J;'0)1'--"1$,K$L%77LF$ $$$$$$$$$$$$$$$$$$$$$$$J%;)/'0$,K$L/0!"AL $$3$===$')9"1$1'()"6$=== "0!
in your plugin: O;)/'0I'0)1'--"1JJ?'()/05JJ?'()"6=!1%8$!'$+2%7+ $$2%7=;'00";)$G:7%)9GF$J;'0)1'--"1$,K$L7-(5/0LF$ $$$$$$$$$$$$$$$$$$$$$$$J%;)/'0$,K$L/0!"AL "0! in your app: O;)/'0I'0)1'--"1JJ?'()/05JJ?'()"6=!1%8$!'$+2%7+ $$3$===$')9"1$1'()"6$=== $$2%7=;'00";)$G:7%)9GF$J;'0)1'--"1$,K$L%77LF$ $$$$$$$$$$$$$$$$$$$$$$$J%;)/'0$,K$L/0!"AL $$3$===$')9"1$1'()"6$=== "0!
Ticket #2592 (also Ticket #329)
785*$+,#-&$#)&785*$+,#-.!) 2'!(-"$P<H-(5/0 $$!"#$6"-#=%!!.1'()"6B 7"* C $$$$2%7=;'00";)$L:6)(##LF$J;'0)1'--"1$,K$L)9/056L $$"0! "0! O;)/'0I'0)1'--"1JJ?'()/05JJ?'()"6=!1%8$!'$+2%7+ $$3$<'(1$%77$1'()"6=== $$P<H-(5/0=%!!.1'()"6B2%7C $$3$");=== "0!
what’s missing?
public assets
copy
file clash
83+!5*$+,#-&#-%'"$$.!) 2<./2%5"6$,$H%)90%2"=0"8B@/-"=!/10%2"B..@QR4..CC$S$ $$$$$$$$$$$$$$L%66")6:/2%5"6L )%15")$,$?%/-6=1'')$S$L7(&-/;:/2%5"6:2<.7-(5/0L @/-"T)/-6=2U!/1.7B)%15")C 2<./2%5"6=;9/-!1"0="%;9$!'$+"+$ $$$$@/-"T)/-6=;7.1B"F$)%15")$S$"=&%6"0%2"C$ "0!
83+!5*$+,#-&#-%'"$$.!) 2<./2%5"6$,$H%)90%2"=0"8B@/-"=!/10%2"B..@QR4..CC$S$ $$$$$$$$$$$$$$L%66")6:/2%5"6L )%15")$,$?%/-6=1'')$S$L7(&-/;:/2%5"6:2<.7-(5/0L )%15")=2%U".6<2-/0UB2<./2%5"6C$(0-"66$)%15")="A/6)>
migrations
simple DSL
rollback
!&:2/51%)": version $$VWWXWYWYYVYVZ[.%-79%=1& VWWXWYWVY[VZ[\.&")%=1& 20090101121234 20090102142345 7-(5/0:!&:2/51%)": 2008123123456 $$VWW]YVZYZ[\^.5%22%=1&
1%U"$!&J1'--&%;U version P/51%)'1=1'--&%;U 20090101121234 P/51%)'13;(11"0).D"16/'0 20090102142345 P/51%)'132/51%)"!=-%6) 2008123123456 P/51%)'1=5").%--.D"16/'06 BL_4R4I`$D"16/'0$@?aP$ $ $ $$6;9"2%.2/51%)/'06LC =2%7BbJ)'./C=6'1)
it gets worse
!&:2/51%)": version $$WWY.%-79%=1& WWV.&")%=1& 001 002 7-(5/0:!&:2/51%)": $$WWY.5%22%=1&
http://www.flickr.com/photos/bk2204/475332962/
single timeline
You app migration 1 plugin migration 1 app migration 2 app migration 3 Me plugin migration 2 install upgrade
app migration 1 plugin migration 1 You app migration 2 app migration 3 plugin migration 2
!&:2/51%)": $$WWY.%-79%=1& WWV.&")%=1& WWZ.7-(5/0.)'.WWY=1& WW[.!"-)%=1& 7-(5/0:!&:2/51%)": $$WWY.5%22%=1&
Symlink? !&:2/51%)": $$WWY.%-79%=1& WWV.&")%=1& Reference? WWZ.7-(5/0.)'.WWY=1& WW[.!"-)%=1& Copy & 7-(5/0:!&:2/51%)": Retimestamp? $$WWY.5%22%=1&
Ticket #2058 interblah.net/plugin-migrations
my recommendation? (for the moment, at least)
write a generator (within your plugin) c$6;1/7):5"0"1%)"$%;)6.%6.#(.2/51%)/'06 $$$$ $$$"A/6)6$$!&:2/51%)" $$$;1"%)"$$!&:2/51%)":VWWXW\W\YYYZZd.&-%9=1& c$===
techniques
overriding functionality
views just work
controllers
straight override
module
namespaced
playing nice with the class cache
1/23*8/36/1**$#2"'#3-43-'!3$$(!/ < < ! 9"%/)((-/!(73:(;/6!37/'9(/73;+$(/ < < < < '!((/)+'/#%/%'#$$/"2'#:(< <
O;)/D"_(77'1)JJe"7"0!"0;/"6=-'%!.'0;".7%)96
ApplicationController AppController PluginController
ApplicationController PluginController
23-6#,&(-:#!3-7(-'.!) ?%/-6JJQ0/)/%-/f"1=1(0$!'$+;'0#/5+ $$3$");=== $$;'0#/5=1"-'%!.7-(5/06$,$)1(" $$ "0!
83+!5*$+,#-&"**&23-'!3$$(!%&,33;523-'!3$$(!.!) ;-%66$g''!I'0)1'--"1$h$=== $$(0-'%!%&-" $$ $$3$");$=== "0!
init.rb woes
785*$+,#-&#-#'.!) ;'0#/5=)'.71"7%1"$!' $$_'2"O77I-%66="A)"0!BP<i"9%D/'(1C $$ "0!
testing
ApplicationController AppController PluginController
ApplicationController Their Code Your Code PluginController
� � � �
unit test?
test in your own rails environment?
plugin_test_helper
I care about testing my chunk
You care about testing your whole app
empower the developer
avoiding fail
;%6"$;'!"=;'06(2"1 $$89"0$;'!"=%()9'1 $$$$1"(6"=2'6)-<$,j$:"##";)/D": $$89"0$1%0!B!"D"-'7"1C $$$$1"(6"=)1/;U/"1.&().7'66/&-"B)1("C $$"-6" $$$$1"(6"='D"11%)"!N "0!
consume wisely
Nutrition Facts Serving Size 14 kloc Amount Per Serving 1 bad engine Calories 10,666 % Daily Value* Total Fat 2674g 98 % 34 % Long Methods 1578g 7 % God Objects 326g Stress 320mg 119 % Hairloss 45g 45.8 % Technical Debt 13g 87 % 34 % Untested Code 1578mg 7 % Hidden Bugs 326mg Benefit 1mg 0.1 %
you will not be able to write some engines.
you will not be able to use some engines.
extract specific functionality
establish some clear integration points
you are customer #1
READ the CODE
james@lazyatom.com FIN lets@gofreerange.com
Recommend
More recommend