Date post: | 18-Jul-2015 |
Category: |
Technology |
Upload: | kevin-gisi |
View: | 675 times |
Download: | 3 times |
September 11, 2010
It’s Time to Repay Your DebtWindy City Rails
Kevin W. Gisi
Key Points
✤ Releasing Gems is ridiculously easy!
✤ You don’t have to be Matz!
✤ If you’ve ever DRYed your codebase, you’re probably ready
Before Hook
✤ before_filter :filter_method
✤ before_filter :filter_method, :only => [:foo, :bar]
✤ before_filter :filter_method, :except => :baz
class Foo include Filters
before_filter :before_method after_filter :after_method, :only => :bar def foo(x) puts "foo #{x}" end
def bar puts "bar" end
def before_method puts "before_method" and return true end
def after_method puts "after_method" and return true end
end
module Filters class << self def included(mod) mod.extend(Filters::ClassMethods) mod.instance_methods(false).each do |method| mod.add_global_hook(method) end end end
module ClassMethods # Real methods end end
module ClassMethods
def before_filter(hook_method,options={}) options.keys.each{|k|options[k] = [options[k]].flatten} (@@before_hooks||={})[hook_method.to_sym] = options end
def after_filter(hook_method,options={}) options.keys.each{|k|options[k] = [options[k]].flatten} (@@after_hooks||={})[hook_method.to_sym] = options end
end
before_filter :method, :only => :foo
# options[:only] => [:foo]
after_filter :method, :except => [:foo]
# options[:only] => [:foo]
Hook Tactics
✤ Alias the original method :foo => :__foo
✤ Rewrite :foo
✤ Run any before_hooks
✤ Run the original method (if the before_hooks returned true)
✤ Run any after_hooks
def add_global_hook(method) alias_method "__#{method}", method define_method method do |*args,&block| @@before_hooks ||= {} @@after_hooks ||= {} @@before_hooks.keys.each do |hook| unless (@@before_hooks[hook][:except]||[]).include?(method) || (@@before_hooks[hook][:only] && !@@before_hooks[hook][:only].include?(method)) return unless send(hook) end end unless @@before_hooks[method] || @@after_hooks[method]
returnable = send("__#{method}",*args,&block)
@@after_hooks.keys.each do |hook| unless (@@after_hooks[hook][:except]||[]).include?(method) || (@@after_hooks[hook][:only] && !@@after_hooks[hook][:only].include?(method)) return unless send(hook) end end unless @@before_hooks[method] || @@after_hooks[method] return returnable end end
def add_global_hook(method) alias_method "__#{method}", method define_method method do |*args,&block| @@before_hooks ||= {} @@after_hooks ||= {} @@before_hooks.keys.each do |hook| unless (@@before_hooks[hook][:except]||[]).include?(method) || (@@before_hooks[hook][:only] && !@@before_hooks[hook][:only].include?(method)) return unless send(hook) end end unless @@before_hooks[method] || @@after_hooks[method]
returnable = send("__#{method}",*args,&block)
@@after_hooks.keys.each do |hook| unless (@@after_hooks[hook][:except]||[]).include?(method) || (@@after_hooks[hook][:only] && !@@after_hooks[hook][:only].include?(method)) return unless send(hook) end end unless @@before_hooks[method] || @@after_hooks[method] return returnable end end
def add_global_hook(method) alias_method "__#{method}", method define_method method do |*args,&block|
@@before_hooks.keys.each do |hook| unless return unless send(hook) end end unless @@before_hooks[method] || @@after_hooks[method]
returnable = send("__#{method}",*args,&block)
@@after_hooks.keys.each do |hook| unless
return unless send(hook) end end unless @@before_hooks[method] || @@after_hooks[method] return returnable end end
module Filters class << self def included(mod) mod.extend(Filters::ClassMethods) mod.instance_methods(false).each do |method| mod.add_global_hook(method) end end end
module ClassMethods # ... def method_added(method) add_global_hook(method) unless method.to_s[0,2] == "__" || instance_methods.include?("__#{method}".to_sym) end end end
class Foo include Filters
before_filter :before_method after_filter :after_method, :only => :bar def foo(x) puts "foo #{x}" end
def bar puts "bar" end
def before_method puts "before_method" and return true end
def after_method puts "after_method" and return true end
end
Let’s Make It A Gem!
Gem::Specification.new do |s| s.name = "filt" s.version = "0.0.1" s.summary = "before and after filters for Ruby" s.files = ["lib/filt"]end
filt.gemspec
Let’s Share The Gem!
✤ gem build filt.gemspec
✤ gem push filt-0.0.1.gem
✤ http://rubygems.org/gems/filt
John Doe Programmer
✤ Windows 7 machine (moderate hardware)
✤ Visual Studio
✤ Microsoft SQL Server
✤ A little bit of PHP
✤ Minimal web experience
This Isn’t Bad!
✤ Choice is important!
✤ There are many “right ways”
✤ Flexibility allows us to create better solutions
OpenPGP
module OpenPGP class Message include Enumerable
# ...
def self.decrypt(data, options = {}, &block) raise NotImplementedError # TODO end endend
What Is A Product?
✤ Utility
✤ Aesthetics
Aesthetics
resources :products do resource :category member do post :short end collection do get :long endend match "/posts/github" => redirect("http://github.com/rails.atom")
map.resources :products, :member => {:short => :post}, :collection => {:long => :get} do |products| products.resource :categoryend
Utility
✤ Solves a problem
Agile (according to rumor)
✤ Do the absolute bare minimum to get something delivered
Agile
✤ Do the absolute bare minimum to get something delivered*
Delivered, n.
✤ Coded
✤ Deployed
✤ Supported
✤ Tested
✤ Extensible
✤ Usable by the client
Open-Source Is A Marketplace
The Lazy Programmer’s Manifesto
✤ I want to write code once
✤ I want to be able to read code without having to refer to external docs
✤ I want to be able to rely on other libraries
✤ I want to use adaptable solutions for numerous problems
✤ I want to always be working on something new
Products For A Lazy Market
Development For A Lazy Market
Idea Filtering
✤ To share
✤ Business value
✤ Practical use
✤ To learn
✤ No requirements!
✤ Don’t post it publicly!
Testing
✤ We all say we do it!
✤ RSpec and Cucumber are both easy to set up for gems
✤ Design verification tool
Extensible
✤ Write clean code (don’t post a spike)
✤ Have a peer review your stuff
✤ Follow the Unix philosophy: do one thing really well
✤ Leverage other gems!
Documented
✤ Who’s looking at your code if it’s on GitHub, RubyGems?
✤ RDoc, YARD, etc
✤ Getting Started
✤ Blog posts!
Supported
✤ Put your name on it
✤ Answer your emails, damnit
✤ Accept patches (at minimum)
Be Honest
✤ Don’t be too proud to hand over the reins
✤ If your project is worth supporting, someone will step up
✤ Be a net-positive for the community
✤ Don’t announce things if they’re not done
But, But, But!!!
✤ Don’t post it
✤ Post it in a limited venue
✤ Put a disclaimer on your project
How Does The Internet Filter Stupid?
✤ It doesn’t?
✤ Making tasks difficult
✤ Having enough eyes
Matz Wisdom
✤ “Ruby treats you like a grown-up programmer”
What Happens When Grown-Ups Have Too Much Fun?
How To Be A Good Parent
✤ Don’t create sensory overload
✤ Spoon-feed sometimes
✤ Remember you’re used to the status quo
✤ Be a mentor
✤ Provide solutions to problems, not blocks of code
It’s Time To Repay Your Debt
Thank You!
✤ Kevin W. Gisi
✤ Twitter: @gisikw
✤ http://spkr8.com/t/4414