DSL Powered by Rabbit 2.1.2
DSL
Yukio Goto
sg.rb
2014/04/29
DSL Powered by Rabbit 2.1.2
Who am I ?
Yukio Goto
favorite
Ruby, emacs, zsh, tennis✓
✓
work
Rakuten Asia Pte. Ltd.✓
As sen...
DSL Powered by Rabbit 2.1.2
IDs
github
https://github.com/byplayer/
twitter
@byplayer
DSL Powered by Rabbit 2.1.2
Today's target
use DSL
-*-*-*-*-*-*-
making DSL
DSL Powered by Rabbit 2.1.2
DSL
What is DSL ?
DSL Powered by Rabbit 2.1.2
DSL
DSL =
Domain Specific
Language
DSL Powered by Rabbit 2.1.2
external DSL
SQL✓
SELECT id, user_name FROM users
DSL Powered by Rabbit 2.1.2
external DSL
configuration files✓
http {
passenger_root /usr/local/rvm/gems/ruby-2.1.0/gems/pass...
DSL Powered by Rabbit 2.1.2
internal DSL
Rails✓
class User < ActiveRecord::Base
validates :name, presence: true
end
DSL Powered by Rabbit 2.1.2
BTW
By the way
DSL Powered by Rabbit 2.1.2
Did you make DSL ?
Did you make
DSL ?
DSL Powered by Rabbit 2.1.2
use only ?
Do you think
you can only
use DSL?
DSL Powered by Rabbit 2.1.2
No
NO !!!
DSL Powered by Rabbit 2.1.2
You
You
DSL Powered by Rabbit 2.1.2
can
can
DSL Powered by Rabbit 2.1.2
make
make
DSL Powered by Rabbit 2.1.2
your own DSL
your own
DSL
DSL Powered by Rabbit 2.1.2
AND
AND
DSL Powered by Rabbit 2.1.2
Ruby
Ruby
is
DSL Powered by Rabbit 2.1.2
easiest language
one of the most
easiest
language
DSL Powered by Rabbit 2.1.2
making DSL
making DSL
DSL Powered by Rabbit 2.1.2
How to make DSL
How to make
DSL
DSL Powered by Rabbit 2.1.2
before that
Before that
DSL Powered by Rabbit 2.1.2
Benefit of making DSL
DSL makes your Application
easy to write✓
easy to read✓
easy to use✓
✓
DSL Powered by Rabbit 2.1.2
theme
Configuration file using DSL
DSL Powered by Rabbit 2.1.2
config version 1
# singapore-ruby-group.conf
meetup do |conf|
conf.group = 'Singapore-Ruby-Grou...
DSL Powered by Rabbit 2.1.2
how to use
mt = Meetup.load('singapore-ruby-group.conf')
puts mt.group
# => Singapore-Ruby-Gro...
DSL Powered by Rabbit 2.1.2
implementation
# Sample class to load configuration
class Meetup
attr_accessor :group, :organi...
DSL Powered by Rabbit 2.1.2
key point
def self.load
# ...
File.open(path, 'r') do |file|
mt.instance_eval(File.read(path),...
DSL Powered by Rabbit 2.1.2
first point
pass string to 'instance_eval'
def self.load
# ...
File.open(path, 'r') do |file|
m...
DSL Powered by Rabbit 2.1.2
instance_eval
"instance_eval"
DSL Powered by Rabbit 2.1.2
instance_eval
interpretes
String
DSL Powered by Rabbit 2.1.2
instance_eval
as Ruby code
DSL Powered by Rabbit 2.1.2
instance_eval
using Object
context
DSL Powered by Rabbit 2.1.2
instance_eval
In this case,
DSL Powered by Rabbit 2.1.2
instance_eval
configuration
file is
DSL Powered by Rabbit 2.1.2
instance_eval
interpreted as
DSL Powered by Rabbit 2.1.2
instance_eval
Meetup class
source code
DSL Powered by Rabbit 2.1.2
expand instance_eval virtually
def self.load
# File.open(path, 'r') do |file|
# mt.instance_ev...
DSL Powered by Rabbit 2.1.2
easy
quite easy
DSL Powered by Rabbit 2.1.2
but
BUT
DSL Powered by Rabbit 2.1.2
Typing config
Typing 'conf.'
DSL Powered by Rabbit 2.1.2
is is
is not
DSL Powered by Rabbit 2.1.2
sexy
sexy
DSL Powered by Rabbit 2.1.2
Is it sexy ?
meetup do |conf|
conf.group = 'Singapore-Ruby-Group'
conf.organizer = 'Winston Te...
DSL Powered by Rabbit 2.1.2
ideal configuration
# singapore-ruby-group.conf
meetup {
group 'Singapore-Ruby-Group'
organizer...
DSL Powered by Rabbit 2.1.2
readable
readable✓
DRY✓
DSL Powered by Rabbit 2.1.2
Let's use
Let's use
DSL Powered by Rabbit 2.1.2
Ruby's black magic
Ruby's black
magic
DSL Powered by Rabbit 2.1.2
parsing
parsing it
DSL Powered by Rabbit 2.1.2
load
class Meetup
attr_accessor :group, :organizer, :sponsors
def self.load(path)
mt = new
Fil...
DSL Powered by Rabbit 2.1.2
make support class
make support class
MeetupLoader
DSL Powered by Rabbit 2.1.2
make support class
define setter
method
DSL Powered by Rabbit 2.1.2
make support class
not use '='
DSL Powered by Rabbit 2.1.2
make support class
and
DSL Powered by Rabbit 2.1.2
make support class
load function
(meetup) only
DSL Powered by Rabbit 2.1.2
make support class (setter)
class MeetupLoader
def initialize(mt)
@meetup = mt
end
# ...
def g...
DSL Powered by Rabbit 2.1.2
instance_eval again
class MeetupLoader
# ...
def meetup(&block)
instance_eval(&block)
end
# .....
DSL Powered by Rabbit 2.1.2
The point of black magic
instance_eval
again
DSL Powered by Rabbit 2.1.2
instance_eval for block
instance_eval
with block
DSL Powered by Rabbit 2.1.2
changes
changes
DSL Powered by Rabbit 2.1.2
default receiver
default
receiver
DSL Powered by Rabbit 2.1.2
in the block
in the block
DSL Powered by Rabbit 2.1.2
original code
class Meetup
attr_accessor :group, :organizer, :sponsors
def self.load(path)
mt ...
DSL Powered by Rabbit 2.1.2
expand instance_eval virtually 1
def self.load(path)
mt = new
File.open(path, 'r') do |file|
l...
DSL Powered by Rabbit 2.1.2
instance_eval with block
class MeetupLoader
# ...
def meetup(&block)
instance_eval(&block)
end...
DSL Powered by Rabbit 2.1.2
expand instance_eval virtually 2
def meetup(&block)
# instance_eval(&block)
#{
self.group 'Sin...
DSL Powered by Rabbit 2.1.2
The trick
The trick
DSL Powered by Rabbit 2.1.2
of
of
DSL Powered by Rabbit 2.1.2
Ruby's black magic
Ruby's black
magic
DSL Powered by Rabbit 2.1.2
is
is
DSL Powered by Rabbit 2.1.2
instance_eval with block
instance_eval
with block
DSL Powered by Rabbit 2.1.2
expand instance_eval virtually 2
def meetup(&block)
# instance_eval(&block)
#{
self.group 'Sin...
DSL Powered by Rabbit 2.1.2
Today
Today,
DSL Powered by Rabbit 2.1.2
I
I
DSL Powered by Rabbit 2.1.2
don't
don't
DSL Powered by Rabbit 2.1.2
talk about
talk about
DSL Powered by Rabbit 2.1.2
caution points
caution points
DSL Powered by Rabbit 2.1.2
caution points
security✓
handle method_missing✓
handle syntax error✓
DSL Powered by Rabbit 2.1.2
source code
https://github.com/byplayer/meetup_config✓
https://github.com/byplayer/
meetup_confi...
DSL Powered by Rabbit 2.1.2
take a way
You can make DSL✓
instance_eval is interesting✓
DSL Powered by Rabbit 2.1.2
Hiring
Rakuten Asia Pte. Ltd.
wants to hire
Server side Application
Engineer (Ruby, java)
✓
iO...
DSL Powered by Rabbit 2.1.2
Any question ?
Any question ?
DSL Powered by Rabbit 2.1.2
Thank you
Thank you
for listening
Upcoming SlideShare
Loading in …5
×

How to make DSL

559 views
433 views

Published on

This is slide how to make DSL using Ruby.
You can understand making your own DSL.

Published in: Technology
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
559
On SlideShare
0
From Embeds
0
Number of Embeds
8
Actions
Shares
0
Downloads
2
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

How to make DSL

  1. 1. DSL Powered by Rabbit 2.1.2 DSL Yukio Goto sg.rb 2014/04/29
  2. 2. DSL Powered by Rabbit 2.1.2 Who am I ? Yukio Goto favorite Ruby, emacs, zsh, tennis✓ ✓ work Rakuten Asia Pte. Ltd.✓ As senior application engineer✓ ✓ ✓
  3. 3. DSL Powered by Rabbit 2.1.2 IDs github https://github.com/byplayer/ twitter @byplayer
  4. 4. DSL Powered by Rabbit 2.1.2 Today's target use DSL -*-*-*-*-*-*- making DSL
  5. 5. DSL Powered by Rabbit 2.1.2 DSL What is DSL ?
  6. 6. DSL Powered by Rabbit 2.1.2 DSL DSL = Domain Specific Language
  7. 7. DSL Powered by Rabbit 2.1.2 external DSL SQL✓ SELECT id, user_name FROM users
  8. 8. DSL Powered by Rabbit 2.1.2 external DSL configuration files✓ http { passenger_root /usr/local/rvm/gems/ruby-2.1.0/gems/passenger-4.0.29; passenger_ruby /usr/local/rvm/wrappers/ruby-2.1.0/ruby; include mime.types; default_type application/octet-stream; # ... }
  9. 9. DSL Powered by Rabbit 2.1.2 internal DSL Rails✓ class User < ActiveRecord::Base validates :name, presence: true end
  10. 10. DSL Powered by Rabbit 2.1.2 BTW By the way
  11. 11. DSL Powered by Rabbit 2.1.2 Did you make DSL ? Did you make DSL ?
  12. 12. DSL Powered by Rabbit 2.1.2 use only ? Do you think you can only use DSL?
  13. 13. DSL Powered by Rabbit 2.1.2 No NO !!!
  14. 14. DSL Powered by Rabbit 2.1.2 You You
  15. 15. DSL Powered by Rabbit 2.1.2 can can
  16. 16. DSL Powered by Rabbit 2.1.2 make make
  17. 17. DSL Powered by Rabbit 2.1.2 your own DSL your own DSL
  18. 18. DSL Powered by Rabbit 2.1.2 AND AND
  19. 19. DSL Powered by Rabbit 2.1.2 Ruby Ruby is
  20. 20. DSL Powered by Rabbit 2.1.2 easiest language one of the most easiest language
  21. 21. DSL Powered by Rabbit 2.1.2 making DSL making DSL
  22. 22. DSL Powered by Rabbit 2.1.2 How to make DSL How to make DSL
  23. 23. DSL Powered by Rabbit 2.1.2 before that Before that
  24. 24. DSL Powered by Rabbit 2.1.2 Benefit of making DSL DSL makes your Application easy to write✓ easy to read✓ easy to use✓ ✓
  25. 25. DSL Powered by Rabbit 2.1.2 theme Configuration file using DSL
  26. 26. DSL Powered by Rabbit 2.1.2 config version 1 # singapore-ruby-group.conf meetup do |conf| conf.group = 'Singapore-Ruby-Group' conf.organizer = 'Winston Teo' conf.sponsors = ['Engine Yard', 'Silicon Straits', 'Plug-In@Blk71'] end
  27. 27. DSL Powered by Rabbit 2.1.2 how to use mt = Meetup.load('singapore-ruby-group.conf') puts mt.group # => Singapore-Ruby-Group puts mt.organizer # => Winston Teo puts mt.sponsors.join(', ') # => Engine Yard, Silicon Straits, Plug-In@Blk71
  28. 28. DSL Powered by Rabbit 2.1.2 implementation # Sample class to load configuration class Meetup attr_accessor :group, :organizer, :sponsors def self.load(path) fail "config file not found: #{path}" unless File.exist?(path) mt = Meetup.new File.open(path, 'r') do |file| mt.instance_eval(File.read(path), path) end mt end private def meetup yield self end end
  29. 29. DSL Powered by Rabbit 2.1.2 key point def self.load # ... File.open(path, 'r') do |file| mt.instance_eval(File.read(path), path) end # ... end def meetup yield self end
  30. 30. DSL Powered by Rabbit 2.1.2 first point pass string to 'instance_eval' def self.load # ... File.open(path, 'r') do |file| mt.instance_eval(File.read(path), path) end # ... end
  31. 31. DSL Powered by Rabbit 2.1.2 instance_eval "instance_eval"
  32. 32. DSL Powered by Rabbit 2.1.2 instance_eval interpretes String
  33. 33. DSL Powered by Rabbit 2.1.2 instance_eval as Ruby code
  34. 34. DSL Powered by Rabbit 2.1.2 instance_eval using Object context
  35. 35. DSL Powered by Rabbit 2.1.2 instance_eval In this case,
  36. 36. DSL Powered by Rabbit 2.1.2 instance_eval configuration file is
  37. 37. DSL Powered by Rabbit 2.1.2 instance_eval interpreted as
  38. 38. DSL Powered by Rabbit 2.1.2 instance_eval Meetup class source code
  39. 39. DSL Powered by Rabbit 2.1.2 expand instance_eval virtually def self.load # File.open(path, 'r') do |file| # mt.instance_eval(File.read(path), path) # end meetup do |conf| conf.group = 'Singapore-Ruby-Group' conf.organizer = 'Winston Teo' conf.sponsors = ['Engine Yard', 'Silicon Straits', 'Plug-In@Blk71'] end end
  40. 40. DSL Powered by Rabbit 2.1.2 easy quite easy
  41. 41. DSL Powered by Rabbit 2.1.2 but BUT
  42. 42. DSL Powered by Rabbit 2.1.2 Typing config Typing 'conf.'
  43. 43. DSL Powered by Rabbit 2.1.2 is is is not
  44. 44. DSL Powered by Rabbit 2.1.2 sexy sexy
  45. 45. DSL Powered by Rabbit 2.1.2 Is it sexy ? meetup do |conf| conf.group = 'Singapore-Ruby-Group' conf.organizer = 'Winston Teo' conf.sponsors = ['Engine Yard', 'Silicon Straits', 'Plug-In@Blk71'] end
  46. 46. DSL Powered by Rabbit 2.1.2 ideal configuration # singapore-ruby-group.conf meetup { group 'Singapore-Ruby-Group' organizer 'Winston Teo' sponsors ['Engine Yard', 'Silicon Straits', 'Plug-In@Blk71'] }
  47. 47. DSL Powered by Rabbit 2.1.2 readable readable✓ DRY✓
  48. 48. DSL Powered by Rabbit 2.1.2 Let's use Let's use
  49. 49. DSL Powered by Rabbit 2.1.2 Ruby's black magic Ruby's black magic
  50. 50. DSL Powered by Rabbit 2.1.2 parsing parsing it
  51. 51. DSL Powered by Rabbit 2.1.2 load class Meetup attr_accessor :group, :organizer, :sponsors def self.load(path) mt = new File.open(path, 'r') do |file| loader = MeetupLoader.new(mt) loader.instance_eval(file.read, path) end mt end end
  52. 52. DSL Powered by Rabbit 2.1.2 make support class make support class MeetupLoader
  53. 53. DSL Powered by Rabbit 2.1.2 make support class define setter method
  54. 54. DSL Powered by Rabbit 2.1.2 make support class not use '='
  55. 55. DSL Powered by Rabbit 2.1.2 make support class and
  56. 56. DSL Powered by Rabbit 2.1.2 make support class load function (meetup) only
  57. 57. DSL Powered by Rabbit 2.1.2 make support class (setter) class MeetupLoader def initialize(mt) @meetup = mt end # ... def group(g) @meetup.group = g end def organizer(o) @meetup.organizer = o end # ... end
  58. 58. DSL Powered by Rabbit 2.1.2 instance_eval again class MeetupLoader # ... def meetup(&block) instance_eval(&block) end # ... end
  59. 59. DSL Powered by Rabbit 2.1.2 The point of black magic instance_eval again
  60. 60. DSL Powered by Rabbit 2.1.2 instance_eval for block instance_eval with block
  61. 61. DSL Powered by Rabbit 2.1.2 changes changes
  62. 62. DSL Powered by Rabbit 2.1.2 default receiver default receiver
  63. 63. DSL Powered by Rabbit 2.1.2 in the block in the block
  64. 64. DSL Powered by Rabbit 2.1.2 original code class Meetup attr_accessor :group, :organizer, :sponsors def self.load(path) mt = new File.open(path, 'r') do |file| loader = MeetupLoader.new(mt) loader.instance_eval(file.read, path) end mt end end
  65. 65. DSL Powered by Rabbit 2.1.2 expand instance_eval virtually 1 def self.load(path) mt = new File.open(path, 'r') do |file| loader = MeetupLoader.new(mt) # loader.instance_eval(file.read, path) loader.meetup { group 'Singapore-Ruby-Group' organizer 'Winston Teo' # ... } end #...
  66. 66. DSL Powered by Rabbit 2.1.2 instance_eval with block class MeetupLoader # ... def meetup(&block) instance_eval(&block) end # ... end
  67. 67. DSL Powered by Rabbit 2.1.2 expand instance_eval virtually 2 def meetup(&block) # instance_eval(&block) #{ self.group 'Singapore-Ruby-Group' self.organizer 'Winston Teo' # ... # } end
  68. 68. DSL Powered by Rabbit 2.1.2 The trick The trick
  69. 69. DSL Powered by Rabbit 2.1.2 of of
  70. 70. DSL Powered by Rabbit 2.1.2 Ruby's black magic Ruby's black magic
  71. 71. DSL Powered by Rabbit 2.1.2 is is
  72. 72. DSL Powered by Rabbit 2.1.2 instance_eval with block instance_eval with block
  73. 73. DSL Powered by Rabbit 2.1.2 expand instance_eval virtually 2 def meetup(&block) # instance_eval(&block) #{ self.group 'Singapore-Ruby-Group' self.organizer 'Winston Teo' # ... # } end
  74. 74. DSL Powered by Rabbit 2.1.2 Today Today,
  75. 75. DSL Powered by Rabbit 2.1.2 I I
  76. 76. DSL Powered by Rabbit 2.1.2 don't don't
  77. 77. DSL Powered by Rabbit 2.1.2 talk about talk about
  78. 78. DSL Powered by Rabbit 2.1.2 caution points caution points
  79. 79. DSL Powered by Rabbit 2.1.2 caution points security✓ handle method_missing✓ handle syntax error✓
  80. 80. DSL Powered by Rabbit 2.1.2 source code https://github.com/byplayer/meetup_config✓ https://github.com/byplayer/ meetup_config_ex ✓
  81. 81. DSL Powered by Rabbit 2.1.2 take a way You can make DSL✓ instance_eval is interesting✓
  82. 82. DSL Powered by Rabbit 2.1.2 Hiring Rakuten Asia Pte. Ltd. wants to hire Server side Application Engineer (Ruby, java) ✓ iOS, Android Application Engineer ✓ ✓
  83. 83. DSL Powered by Rabbit 2.1.2 Any question ? Any question ?
  84. 84. DSL Powered by Rabbit 2.1.2 Thank you Thank you for listening

×