Simple Internal DSL with Ruby
I may write up or comment out the code in detail in the future. For the curious, here is a very good post from Gabe Berke-Williams on thoughtbot.com.
To further sharpening your skills, I recommend googling “ruby how to use method_missing” and “instance_eval vs class_eval ruby” - those are key in meta programming Ruby.
# to not pollute the global namespace, wrap your DSL in a module and class
module DslWrapper
class Post
def initialize(user)
@user = user
@post = []
@extras = {}
end
def text(str)
@post << str
self
end
def hashtag(*strs)
strs.each {|str| @post << '#' + str}
self
end
def link(str)
@post << str
self
end
def post_on_facebook
fb_text = @post.join(' ')
begin
if fb_text.length <= 440
puts "#{@user}: #{fb_text}"
puts @extras.inspect unless @extras.empty?
else
raise 'Your post is too long.'
end
rescue
puts "I can't tweet this, your tweet is too long, sorry."
end
end
def method_missing(method, *args)
@extras[method] = args.join(', ')
end
end
end
this is your exposed dsl method
# your exposed DSL method
def post_as(user, text = nil, &block)
post = DslWrapper::Post.new(user)
post.text(text) if text
# by passing the block to instance_eval your
# passed in methods are now run in the scope of Post Class
post.instance_eval(&block) if block_given?
post.post_on_facebook
end
now, let’s see your DSL in action!
# granular style
post_as 'Mark_Z' do
text """
Lorem ipsum dolor sit amet, consectetur adipisicing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua. Ut enim ad minim veniam, quis nostrud exercitation
ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit
esse cillum dolore eu fugiat nulla pariatur. Excepteur
sint occaecat cupidatat non proident, sunt in culpa qui
officia deserunt mollit anim id est laborum.
"""
hashtag 'ruby'
hashtag 'dsl'
link 'http://www.simon-neutert.de'
sexy 'objects'
end
# multiple hashtags in one line
post_as 'Mark_Z' do
text 'my dsl works'
hashtag 'ruby', 'dsl'
link 'http://www.simon-neutert.de'
sexy 'classy'
end
# method chaining (possible, because Post's methods return "self")
post_as 'Mark_Z' do
text("Mic check...").hashtag("one", "two").link('http://www.simon-neutert.de')
sexy 'bit'
end
# in a one liner
post_as 'Mark_Z', 'Hi, I am Mark_Z!'
⬅️ Read previous Read next ➡️