how to make dsl

Post on 11-May-2015

333 Views

Category:

Technology

3 Downloads

Preview:

Click to see full reader

DESCRIPTION

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

TRANSCRIPT

DSL Powered by Rabbit 2.1.2

DSL

Yukio Gotosg.rb

2014/04/29

DSL Powered by Rabbit 2.1.2

Who am I ?

Yukio Gotofavorite

Ruby, emacs, zsh, tennis✓✓

workRakuten Asia Pte. Ltd.✓As senior application engineer✓

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/passenger-4.0.29; passenger_ruby /usr/local/rvm/wrappers/ruby-2.1.0/ruby;

include mime.types; default_type application/octet-stream;

# ...}

DSL Powered by Rabbit 2.1.2

internal DSL

Rails✓

class User < ActiveRecord::Base validates :name, presence: trueend

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

Rubyis

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 Applicationeasy 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.confmeetup do |conf| conf.group = 'Singapore-Ruby-Group' conf.organizer = 'Winston Teo' conf.sponsors = ['Engine Yard', 'Silicon Straits', 'Plug-In@Blk71']end

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

DSL Powered by Rabbit 2.1.2

implementation

# Sample class to load configurationclass 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 endend

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 selfend

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

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_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'] endend

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 Teo' conf.sponsors = ['Engine Yard', 'Silicon Straits', 'Plug-In@Blk71']end

DSL Powered by Rabbit 2.1.2

ideal configuration

# singapore-ruby-group.confmeetup { group 'Singapore-Ruby-Group' organizer 'Winston Teo' sponsors ['Engine Yard', 'Silicon Straits', 'Plug-In@Blk71']}

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 File.open(path, 'r') do |file| loader = MeetupLoader.new(mt) loader.instance_eval(file.read, path) end

mt endend

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 group(g) @meetup.group = g end

def organizer(o) @meetup.organizer = o end # ...end

DSL Powered by Rabbit 2.1.2

instance_eval again

class MeetupLoader # ... def meetup(&block) instance_eval(&block) end # ...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 = new File.open(path, 'r') do |file| loader = MeetupLoader.new(mt) loader.instance_eval(file.read, path) end

mt endend

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 #...

DSL Powered by Rabbit 2.1.2

instance_eval with block

class MeetupLoader # ... def meetup(&block) instance_eval(&block) end # ...end

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

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 'Singapore-Ruby-Group' self.organizer 'Winston Teo' # ... # }end

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_config_ex

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)

iOS, Android Application Engineer

DSL Powered by Rabbit 2.1.2

Any question ?

Any question ?

DSL Powered by Rabbit 2.1.2

Thank you

Thank youfor listening

top related