|
Sunday, 28 February 2010 23:22 |
// Using an XML file to define options OptParseSimple
class OptParseSimple
def initialize(filename, args)
doc = Document.new(File.open('options.xml','r').read)
@options = XPath.match(doc.root, 'records/option[switch!=""]')
switches = @options.map do |option|
switch = option.text('switch')
switch[0] == '-' ? switch : nil
end
switches.compact!
# split the argument switches if grouped e.g. -ltr
args.map! do |arg|
if arg[/^\-[a-zA-Z]+$/] and switches.grep(/#{arg}/).empty? then
arg[1..-1].scan(/./).map {|x| '-' + x}
else
arg
end
end
args.flatten!
a1 = options_match(@options[0], args).flatten.each_slice(2).map {|x| x if x[0]}.compact
options_remaining = XPath.match(doc.root, 'records/option[switch=""]/name/text()')
a2 = args.zip(options_remaining).map(&:reverse)
if a2.map(&:first).all? then
@h = Hash[*(a1+a2).map{|x,y| [x.to_s.to_sym, y]}.flatten]
else
invalid_option = a2.detect {|x,y| x.nil? }.last
raise "invalid option: %s not recognised" % invalid_option
end
end
def to_h()
@h
end
private
def options_match(option, args)
switch, switch_alias = option.text('switch'), option.text('alias')
switch_pattern = switch_alias ? "(%s|%s)" % [switch, switch_alias] : switch
switch_matched, arg_index = args.each_with_index.detect {|x,j| x[/^#{switch_pattern}/]}
key, value = nil
if switch_matched then
value_pattern = option.text('value')
if value_pattern then
# check for equal sign
value = switch_matched[/\=(#{value_pattern})/,1]
# check the next arg
if value.nil? and args.length > 0 then
next_arg = args[arg_index + 1]
# check to make sure it's not the next switch
next_option = @options[1] if @options.length > 1
if next_arg != next_option then
# validate using the regex
value = next_arg[/#{value_pattern}/]
if value then
args.delete_at(arg_index + 1)
else
raise option.text('errors/records/error[last()]')
end
end
else
args.delete_at(arg_index)
end
else
args.delete_at(arg_index)
end
key = option.text('name')
elsif option.text('mandatory').downcase == 'true' then
raise option.text('errors/records/error')
end
pair = [key, value]
@options.shift
next_pair = options_match(@options[0], args) if @options.length > 0
[pair, next_pair]
end
end
 Read more: |
|
Wednesday, 24 February 2010 00:14 |
SELECT a.name as CustomerNumber,
o.name as Name,
c.oppor_prim_address_c as Address,
a.billing_address_postalcode as Postcode,
c.oppor_home_phone_c as HomePhone,
ua.user_name as AssignedTo,
o.date_entered as DateConverted,
IF(c.energex_ergon_frm_faxed_c = 1, 'Yes', 'No') as AGOFormFaxed,
IF(c.site_survey_conducted_c = 1, 'Yes', 'No') as SiteSurveyConducted,
IF(c.recs_payment_rcvd_c = 1, 'Yes', 'No') as RECsPaymentReceived,
IF(c.paperwrk_rcvd_installer_c = 1, 'Yes', 'No') as PaperworkReceivedFromInstaller,
IF(c.roofer_panels_booked_c = 1, 'Yes', 'No') as InstallBooked,
IF(c.instal_complete_c = 1, 'Yes', 'No') as InstallCompleted
FROM opportunities o
LEFT JOIN opportunities_cstm c ON o.id = c.id_c
LEFT JOIN users ua ON ua.id = o.assigned_user_id
LEFT JOIN accounts_opportunities ao ON o.id = ao.opportunity_id
LEFT JOIN accounts a ON a.id = ao.account_id
WHERE o.name != ''
AND CAST(a.billing_address_postalcode as UNSIGNED) BETWEEN CASE LENGTH('$postcode_start')
WHEN 0 THEN 0
ELSE '$postcode_start'
END AND CASE LENGTH('$postcode_end')
WHEN 0 THEN CASE LENGTH('$postcode_start')
WHEN 0 THEN 10000
ELSE '$postcode_start'
END
ELSE '$postcode_end'
END
AND sales_stage = CASE LENGTH('$sales_stage')
WHEN 0 THEN sales_stage
ELSE '$sales_stage'
END
ORDER BY a.billing_address_postalcode ASC Read more: |
|
|
Sunday, 21 February 2010 18:13 |
The following ad-hoc script adds a registration job to each RSF file as well as bulk update the registry file.
template_buffer = File.open('template-register.xml','r').read
doc = Document.new(File.open('dir.xml','r').read)
XPath.each(doc.root, 'records/file[ext=".rsf"]') do |node|
puts node.text('name')
# open the file
filename = node.text('name')
doc_package = Document.new(File.open(filename,'r').read)
# look for job 'register-package'
unless XPath.first(doc_package.root, 'job[@id="register-package"]') then
doc_template = Document.new(template_buffer)
job = doc_template.root.elements['job']
job.elements['script'].cdatas[0].value.gsub!('[package]', filename[/^\w+/])
doc_package.root.add job
File.open(filename, 'w') {|f| doc_package.write f}
end
end
file: template-register.xml
require 'rexml/document'
include REXML
doc = Document.new(File.open('../packages/dir.xml','r').read)
doc_registry = Document.new(File.open('lucia.xml','r').read)
packages = XPath.first(doc_registry.root, 'system/packages')
XPath.each(doc.root, 'records/file[ext=".rsf"]') do |node|
# open the file
filename = node.text('name')
puts filename
package_name = filename[/^\w+/]
doc_package = Document.new(File.open('../packages/' + filename,'r').read)
# look for job 'register-package'
if XPath.first(doc_package.root, 'job[@id="register-package"]') and not XPath.first(packages, "./[name() = '#{package_name}']") then
package = Element.new package_name.gsub(/\-/,'_')
name = Element.new 'name'; name.text = package_name
url = Element.new 'url'
url.text = "http://rscript.rorbuilder.info/packages/%s.rsf" % package_name
package.add name
package.add url
packages.add package
end
end
File.open('lucia3.xml', 'w') {|f| doc_registry.write f}
Similar to forms here's how the dynamic RSF job works in sinatra_rscript.rb
def display_url_run(url, jobs, extension='.html')
h = {'.xml' => 'text/xml','.html' => 'text/html','.txt' => 'text/plain'}
@content_type = h[extension]
out = run(url, jobs)
content_type @content_type, :charset => 'utf-8' if defined? content_type
out
end
def display_package_run(package_id, job, extension='.html')
jobs = "//job:" + job
#url = "%s%s.rsf" % [@@url_base, package_id]
url = run_projectx('registry', 'get-key', :path => "system/packages/*[name='#{package_id}']/url/text()")
if url then
display_url_run(url.to_s.sub(/^http:\/\/rscript.rorbuilder.info\//,'\0s/open/'),jobs, extension)
#redirect rsf_job.to_s
else
# 404
package_id = 'n404'
url = "%s%s.rsf" % [@@url_base, package_id]
jobs = "//job:package"
display_url_run(url,jobs, extension)
end
end
get '/do/:package_id/:job' do
package_id = params[:package_id] #
job, extension = params[:job][/\.\w{3}$/] ? [$`, $&] : [params[:job], '.html']
display_package_run(package_id, job, extension)
end
 Read more: |
|
Friday, 19 February 2010 06:00 |
 | About Ephemera
Ephemera will comfortably synchronize your ebook reader with Instapaper.com via USB. It works with the Amazon Kindle, Sony readers and pretty much any device capable of reading HTML, Mobipocket or EPUB files. By default, Ephemera gets your unread Instapaper news as single articles. Read one, delete it on your reader, and during the next sync it’ll be archived on Instapaper.com.
If you want it to, Ephemera will automatically start up, sync, and then unmount your reader when it detects the USB connection. Configure the app once, and then just have it work for you — by simply connecting your reader!
|
Read more: |
|