Ruby DSL experiences? - ruby

I don't know anything in Ruby, but i'm pretty interested in DSLs. And DSL seems to be a buzz word for you community.
Do you actually implement DSLs in Ruby for your own purposes ? If so, how complex and how dedicated are they ?
i've seen this question here, but i'm more interested in your everyday experience.
thanks.

Here's another example of a Ruby DSL, it's called Mail, and it's a DSL for sending emails:
mail = Mail.new do
to 'nicolas#test.lindsaar.net.au'
from 'Mikel Lindsaar <mikel#test.lindsaar.net.au>'
subject 'First multipart email sent with Mail'
end
see here: http://github.com/mikel/mail

My own experience writing DSLs in Ruby is quite limited but i've done the following:
(1) An L-System DSL:
Dragon = TexPlay::LSystem.new {
rule "F" => "F"
rule "X" => "X+YF+"
rule "Y" => "-FX-Y"
angle 90
atom "FX"
}
(2) An image manipulation tool:
image.paint {
circle 20, 20, 15, :color => :red
rect 10, 20, 100, 100, :color => :green
pixel 40, 40, :color => :white
}

Its Ruby's speciality, to get everything working very quickly, But it could become tough to manage. I would say, for small or medium DSL projects ruby is awesome. As i haven't created any big DSL project in Ruby, i cannot recommend it(for bigger projects).

Related

Not able to call instance_double twice

I'm writing a test fot rspec to check that items are added into a class that I use like an array
describe '#collection' do
let(:process) {
instance_double("WebServerProcess", :cpu => 33, :mem => 22, :pid => 1, :port => 8000)
}
it 'return the collection' do
WebServersCollection.add process
expect(subject.collection).to eq([process])
end
it 'should add with <<' do
WebServersCollection << process
expect(subject.collection).to eq([process])
end
end
Show me this error
Failure/Error: expect(subject.collection).to eq([process])
# was originally created in one example but has leaked into another example and can no
longer be used. rspec-mocks' doubles are designed to only last for one
example, and you need to create a new one in each example you wish to
use it for.
I think the error tells you everything you need to know.
You can't do that and
you need to create a new one in each example you wish to use it for

Ruby shoes, para.cursor method

My question is concerning the "para" object. Where can I look up all the methods para has? I tried the shoesrb.com manual but all it says is that para is used to render text. I also tried #shoes at Freenode, but no one answered. Seems that no one is online.
I ask because I don't understand what the pounded (###) line does.
str, t = "", nil
Shoes.app :height => 500, :width => 450 do
background rgb(77, 77, 77)
stack :margin => 10 do
para span("TEXT EDITOR", :stroke => red, :fill => white), " * USE ALT-Q TO QUIT", :stroke => white
end
stack :margin => 10 do
t = para "", :font => "Monospace 12px", :stroke => white
t.cursor = -1 ####### I don't understand this line
end
keypress do |k|
case k
when String
str += k
when :backspace
str.slice!(-1)
when :tab
str += " "
when :left ### This is the part I'm interested in
#### Can you suggest a method to put in here. It moves the cursor to the left.
when :alt_q
quit
when :alt_c
self.clipboard = str
when :alt_v
str += self.clipboard
end
t.replace str
end
end
Does the para class have a cursor method? The official documentation has no answer.
I am trying to extend this into a simple text editor but I can't understand how to move the cursor.
I am a novice programer and new to Ruby as well.
Furthermore, where do the Shoes programmers hang out? I tried the mailing list, apparently it's out of service. Is there are specific forum or a different mailing list?
thanks for trying out Shoes.
Yes, Red Shoes a.k.a. Shoes 3 apparently has a cursor method that lets you set the position of the cursor. It's undocumented though, I had to look up in the sources. Your milage may vary using it.
The Shoes mailing list is definitely alive and active. Just send a message to shoes#librelist.com and you should automatically be signed up. That would be the best channel for help on Shoes, for the rest communication happens mostly through Github issues.

Create 3 color conditional formatting with axlsx

With axlsx, the following
color_scale = Axlsx::ColorScale.new do |c_s|
c_s.colors[1].rgb = "FFFFFF00"
end
color_scale.add :type => :percentile, :val => 50, :color => "FF00FF00"
worksheet.add_conditional_formatting("B3:B100", { :type => :colorScale, :operator => :greaterThan, :formula => "100000", :priority => 1, :color_scale => color_scale })
creates a basic 3 color conditional formatting, but the colors are pretty garish, making it hard to distinguish between slightly smaller and slightly larger values.
Is it necessary to reverse-engineer the colors Excel uses in order to create something that looks like the default 3 color conditional formatting that Excel provides?
For color scales, Excel will by default prefer Themes, while Axlsx is currently expecting you to specify exactly what you want. This is partly for interoperability but mostly because I have not ran into a use case that requires similarity to Excel's defaults.
That said, Axlsx should do what it can to give you some sensible defaults and I am sure you can understand how your request is an excellent opportunity to improve this area.
Would you be so kind as to send me a sample xlsx of what you are trying to achieve?
I am sure that I can add a bit of sugar in to make you a bit happier with the results you are seeing now and hopefully benefit the other users of the gem.
UPDATE 2012.11.16
Axlsx has been updated to version 1.3.4 to provide two class methods on ColorScale to create new ColorScale objects with sensible defaults for two-tone and three-tone color scaling.
Examples:
# to make a three tone color scale
color_scale = Axlsx::ColorScale.three_tone
# to make a two tone color scale
color_scale = Axlsx::ColorScale.two_tone
# To make a customized color scale you, pass hashes consisting of
# type, val and color key-value pairs as arguments to the initializer.
# This example that creates the same three tone color scale as
# Axlsx::ColorScale.three_tone
color_scale = Axlsx::ColorScale.new({:type => :min, :val => 0, :color => 'FFF8696B'},
{:type => :percent, :val => '50', :color => 'FFFFEB84'},
{:type => :max, :val => 0, :color => 'FF63BE7B'})

Can you create inputbox with Ruby?

I have used VBScript in the past for QTP and I could use the input box function to display a pop up window.
I am wondering if there is a way to do this with Ruby? I need a popup that will allow the user to input some information before the WATIR script executes.
I looked around StackOverflow but didn't see anything.
Here an example of how to get the messagebox from vbscript in Ruby, i'll try to get the inputbox in the same way
require "Win32API"
message = "This is a sample Windows message box generated using Win32API"
title = "Win32API from Ruby"
api = Win32API.new('user32','MessageBox',['L', 'P', 'P', 'L'],'I')
api.call(0,message,title,0)
Maybe this example code helps you (win32 only):
require 'win32ole'
def inputbox( message, title="Message from #{__FILE__}" )
vb_msg = %Q| "#{message.gsub("\n",'"& vbcrlf &"')}"|
vb_msg.gsub!( "\t", '"& vbtab &"' )
vb_msg.gsub!( '&""&','&' )
vb_title = %Q|"#{title}"|
# go!
sc = WIN32OLE.new( "ScriptControl" )
sc.language = "VBScript"
sc.eval(%Q|Inputbox(#{vb_msg}, #{vb_title})|)
#~ sc.eval(%Q|Inputbox(#{vb_msg}, #{vb_title}, aa,hide)|)
end
def popup(message)
wsh = WIN32OLE.new('WScript.Shell')
wsh.popup(message, 0, __FILE__)
end
str = "a | does not break it...\n\nOne\n\tTwo tabbed\nThree..."
res = inputbox( str, "demonstration | title")
popup %Q|When asked\n\n"#{str}"\n\nyou answered:\n#{res}|
This results in:
It follows a popup box with.
See also http://rubyonwindows.blogspot.com/2007/04/ruby-excel-inputbox-hack.html
Since i can't find an inputbox api for windows here is what i do most of the time if i need some simple dialog. Unlike red shoes it is just a gem so easy to install.
require 'green_shoes'
Shoes.app{
e = edit_line
button("Click me!"){alert("You entered." + e.text)}
}
Ruby is a programing/scripting language, so on it's own it doesn't do any kind of GUI or Graphics related stuff. That being said there are quite a few projects and frameworks that use Ruby to accomplish the type of thing you are looking for. The big ones are Ruby on Rails that uses Ruby to create web applications, and Shoes which is for creating computer applications.
There is also this question
What's the best/easiest GUI Library for Ruby?
I would suggest shoes, it's a cross-platform toolkit for writing graphical apps.
I used it and it's pretty cool, you can do something like:
Shoes.app :width => 300, :height => 200 do
stack do
edit_line :width => 400
end
end

Watermarking with Prawn (using templates)

I need to be able to watermark a document that was created from a template. I have the following code right now:
# Note: the raw PDF text (body variable below) is sent from a remote server.
Prawn::Document.new(:template => StringIO.new(body), :page_size =>
'A4') do |document|
# ... including other pages and sections to the template here ...
# watermark
d.page_count.times do |i|
d.go_to_page i
d.stroke_line [d.bounds.left, d.bounds.bottom], [d.bounds.right, d.bounds.top]
d.draw_text "Watermark", :rotate => 45, :at => [100,100], :size => 100
end
end
This is ignoring the templated pages for some reason that I can't comprehend. Now here's where the plot thickens: if the server adds a watermark, then this code will work as expected (e.g. straight Ruby code = no overlaying text on the non-prawn-generated pages, yet watermarking works on a pre-watermarked template). My only guess is there is some way to create a z-index/layer that the server is doing but Prawn itself cannot.
Here is a portion of the code from the server that does the PDF
generation itself, this does the watermarking using iText:
PdfStamper stamper = new PdfStamper(...);
PdfContentByte over = stamper.GetOverContent(i + 1);
over.BeginText();
over.SetTextMatrix(20, 40);
over.SetFontAndSize(bf, 20);
over.SetColorFill(new Color(97, 150, 58));
over.ShowTextAligned(Element.ALIGN_CENTER,
watermarkText,
document.PageSize.Width / 2,
document.PageSize.Height / 2,
55);
over.EndText();
over.Stroke();
If that runs before I use the raw data in Prawn I can watermark, go
figure.
So my questions are:
Anyone know how I can achieve the same effect using prawn instead
of a hybrid? I'd rather handle the watermarking locally.
Is there a basic equivalent to GetOverContent() in Prawn?
Is there a better way to get a string of raw PDF data into Prawn
without using :template and StringIO? (I saw the #add_content method
but that didn't work)
TL;DR: I need to float text above the Prawn templated text a la
watermarking the document.
Any insight or paths I can research will be appreciated. If this
makes no sense I can clarify.
You could try stamping the document.
create_stamp("watermark") do
rotate(30, :origin => [-5, -5]) do
stroke_color "FF3333"
stroke_ellipse [0, 0], 29, 15
stroke_color "000000"
fill_color "993333"
font("Times-Roman") do
draw_text "Watermark", :at => [-23, -3]
end
fill_color "000000"
end
end
stamp_at "watermark", [210, 210]
create_stamp("stamp") do
fill_color "cc0000"
text_rendering_mode(:fill_stroke) do
transparent(0.5){
text_box "WATERMARK",
:size => 50,
:width => bounds.width,
:height => bounds.height,
:align => :center,
:valign => :center,
:at => [0, bounds.height],
:rotate => 45,
:rotate_around => :center
}
end
end
repeat (:all) do
stamp("stamp")
end

Resources