Your SlideShare is downloading. ×
0
Dsl
Dsl
Dsl
Dsl
Dsl
Dsl
Dsl
Dsl
Dsl
Dsl
Dsl
Dsl
Dsl
Dsl
Dsl
Dsl
Dsl
Dsl
Dsl
Dsl
Dsl
Dsl
Dsl
Dsl
Dsl
Dsl
Dsl
Dsl
Dsl
Dsl
Dsl
Dsl
Dsl
Dsl
Dsl
Dsl
Dsl
Dsl
Dsl
Dsl
Dsl
Dsl
Dsl
Dsl
Dsl
Dsl
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Dsl

1,031

Published on

Writing a DSL in Ruby

Writing a DSL in Ruby

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
1,031
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
31
Comments
0
Likes
1
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Transcript

    1. Writing a DSL in Ruby Why Ruby makes it soooo easy!
    2. DSL!!!!11one
    3. domain specific language TL;DR➡ Customized to specific problem domain➡ Evaluated in context of the domain➡ Helps creating ubiquitous language
    4. internal vs. external„Internal DSLs are particular ways of using a host language to give the host language the feel of a particular language.“„External DSLs have their own custom syntaxand you write a full parser to process them.“
    5. internal vs. external„Internal DSLs are particular ways of using a host language to give the host language the feel of a particular language.“„External DSLs have their own custom syntaxand you write a full parser to process them.“
    6. internal vs. external„Internal DSLs are particular ways of using a host language to give the host language the feel of a particular language.“ er wl Fo tin ar„External DSLs have their own custom syntax Mand you write a full parser to process them.“
    7. Rails, collection of DSLs • Routes • Tag- / Form-Helpers • Builder • Associations, Migrations, ... • Rake / Thor • Bundler • [...]
    8. all about API designRuby makes it easy to create DSL: • expressive & concise syntax • open classes • mixins • operator overloading • [...]
    9. Gregory Brown Russ Olsen
    10. DSL by EXAMPLE
    11. Method Paramslink_to "Articles", { :controller => "articles" }, :id => "news", :class => "article"
    12. Method Paramslink_to "Articles", { :controller => "articles" }, :id => "news", :class => "article"def doit_with(some, parameters) # does itend
    13. Method Paramslink_to "Articles", { :controller => "articles" }, :id => "news", :class => "article"def doit_with(some, parameters) def doit_with(mandatory, optional=nil, parameters=nil) # does it # does itend end
    14. Method Paramslink_to "Articles", { :controller => "articles" }, :id => "news", :class => "article"def doit_with(some, parameters) def doit_with(mandatory, optional=nil, parameters=nil) # does it # does itend enddef doit_with(options={:named => parameter}) # does itend
    15. Method Paramslink_to "Articles", { :controller => "articles" }, :id => "news", :class => "article"def doit_with(some, parameters) def doit_with(mandatory, optional=nil, parameters=nil) # does it # does itend enddef doit_with(options={:named => parameter}) def doit_with(mandatory, *optional_paramters) # does it # does itend end
    16. Method Paramslink_to "Articles", { :controller => "articles" }, :id => "news", :class => "article"def doit_with(some, parameters) def doit_with(mandatory, optional=nil, parameters=nil) # does it # does itend enddef doit_with(options={:named => parameter}) def doit_with(mandatory, *optional_paramters) # does it # does itend end def doit_with(*args) options = args.pop if Hash === args.last name = args.first # [...] raise ArgumentError, Bad combination of parameters unless args.size == 1 # does it end
    17. BlocksTwitter.configure do |config| config.consumer_key = YOUR_CONSUMER_KEY config.consumer_secret = YOUR_CONSUMER_SECRETend
    18. Blocks Twitter.configure do |config| config.consumer_key = YOUR_CONSUMER_KEY config.consumer_secret = YOUR_CONSUMER_SECRET enddef doit_with(&explicit_block) explicit_block.callend
    19. Blocks Twitter.configure do |config| config.consumer_key = YOUR_CONSUMER_KEY config.consumer_secret = YOUR_CONSUMER_SECRET enddef doit_with(&explicit_block) def doit_with_implicit_block explicit_block.call yield if block_given?end end
    20. Blocks Twitter.configure do |config| config.consumer_key = YOUR_CONSUMER_KEY config.consumer_secret = YOUR_CONSUMER_SECRET enddef doit_with(&explicit_block) def doit_with_implicit_block explicit_block.call yield if block_given?end end def doit_with_block_for_configuration yield self end
    21. Blocks Twitter.configure do |config| config.consumer_key = YOUR_CONSUMER_KEY config.consumer_secret = YOUR_CONSUMER_SECRET enddef doit_with(&explicit_block) def doit_with_implicit_block explicit_block.call yield if block_given?end end def doit_with_block_for_configuration yield self enddef doit_with(&arity_sensitive_block) arity_sensitive_block.call foo, bar if arity_sensitive_block.arity == 2end
    22. Instance EvalTwitter.configure do |config| config.consumer_key = YOUR_CONSUMER_KEY config.consumer_secret = YOUR_CONSUMER_SECRETend
    23. Instance EvalTwitter.configure do |config| consumer_key = YOUR_CONSUMER_KEY config.consumer_key = YOUR_CONSUMER_KEY consumer_secret = YOUR_CONSUMER_SECRET config.consumer_secret = YOUR_CONSUMER_SECRETend
    24. Instance EvalTwitter.configure do |config| consumer_key = YOUR_CONSUMER_KEY config.consumer_key = YOUR_CONSUMER_KEY consumer_secret = YOUR_CONSUMER_SECRET config.consumer_secret = YOUR_CONSUMER_SECRETend def doit_with(&instance_eval_block) if instance_eval_block.arity == 0 # could also be class_eval, module_eval self.instance_eval(&instance_eval_block) else instance_eval_block.call self end end
    25. Method MissingClient.find_by_firstname_and_lastname_and_gender(uschi, mueller, :female)
    26. Method MissingClient.find_by_firstname_and_lastname_and_gender(uschi, mueller, :female) METHOD_PATTERN = /^find_by_/ def method_missing(method, *args, &block) if method.to_s =~ METHOD_PATTERN # finder magic else super end end
    27. Method MissingClient.find_by_firstname_and_lastname_and_gender(uschi, mueller, :female) METHOD_PATTERN = /^find_by_/ METHOD_PATTERN = /^find_by_/ def method_missing(method, *args, &block) if method.to_s =~ METHOD_PATTERN def method_missing(method, *args, &block) # finder magic if method.to_s =~ METHOD_PATTERN else # finder magic super else end end super end end respond_to?(method) def return true if method =~ METHOD_PATTERN super end
    28. Code Generation client.firstname = uschi puts client.lastname
    29. Code Generation client.firstname = uschi puts client.lastname def generate(name) self.class.send(:define_method, name){puts name} eval("def #{name}() puts #{name} end") def some_method(name) puts name end # [...] end
    30. Makrosclass Client < ActiveRecord::Base has_one :address has_many :orders belongs_to :roleend
    31. Makrosclass Client < ActiveRecord::Base has_one :address has_many :orders belongs_to :roleend class << self def has_something # macro definition end end
    32. Hooks$ ruby simple_test.rb
    33. Hooks$ ruby simple_test.rb at_exit do # shut down code end
    34. Hooks $ ruby simple_test.rb at_exit do # shut down code endinherited, included, method_missing, method_added,method_removed, trace_var, set_trace_func, at_exit ...
    35. Hooks $ ruby simple_test.rb at_exit do # shut down code endset_trace_func proc { |event, file, line, id, binding, classname| inherited, included, method_missing, method_added, printf "%8s %s:%-2d trace_var, set_trace_func, line, id,... method_removed, %10s %8sn", event, file, at_exit classname}
    36. Core Extensions text.blank?
    37. Core Extensions text.blank? class Object def blank? nil? || (respond_to?(:empty?) && empty?) end end
    38. Core Extensions text.blank? class Object def blank? nil? || (respond_to?(:empty?) && empty?) end unless method_defined?(:blank?) end
    39. Core Extensions text.blank?module MyGem class Object module CoreExtensions module blank? def Object defnil? || (respond_to?(:empty?) && empty?) blank? end unless method_defined?(:blank?) respond_to?(:empty?) ? empty? : !self end end end endendObject.send :include, MyGem::CoreExtensions::Object
    40. Ruby techniques✓Method Params ✓Makros✓Blocks ✓Code generation✓Instance Eval ✓Hooks✓Method Missing ✓Core Extensions
    41. External DSLRuby Tools: • Switch Cases • Regular ExpressionsRuby Parser: • Treetop • RACC
    42. Links★ Eloquent Ruby★ Ruby Best Practices★ Domain Specific Languages★ Rebuil★ Treetop
    43. Over and Out
    44. Over and Out

    ×