Here a getting started tutorial for Sashimi
.
Sashimi: Getting Started Tutorial 0
Released Sashimi 0.1.6 0
I just released a new version of Sashimi, with tiny fixes and a new home! In fact the project is also hosted on RubyForge, now you can install the gem with:
$ (sudo) gem install sashimi
or with:
$ (sudo) gem install jodosha-sashimi --source=http://gems.github.com
If you wish, you can visit the project pages on GitHub and on RubyForge.
UPDATE The release 0.1.6 is broken, you are strongly encouraged to update your gem with the newest 0.1.7.
Ruby: Class Methods Proxy 2
Did you ever used class methods inside your instance methods? If yes, you probably noticed how frustrating can be to use the self.class.my_class_method syntax. A solution could be to create a private method which encapsulates the class one.
class Repository
def self.path
@@path
end
def print_path
puts path
end
private
def path
self.class.path
end
end
In the above example, #print_path can print the @@code value, without worrying about it's a class value, because we have wrapped it.
When I developed Sashimi I've widely used this technique, with a bad impact on the code duplication, and in order to DRY-up my code I extended the Ruby's Class class in this way:
class Class
def class_method_proxy(*method_names)
method_names.each do |m|
self.class_eval %{
# Proxy method for <tt>#{self.class.name}##{m}</tt>
def #{m}(*args)
self.class.#{m}(*args)
end
private :#{m}
}, __FILE__, __LINE__
end
end
end
This approach allow us to annotate our classes, choosing which class methods should be available as private methods.
Now, our example class should look like the following:
class Repository
def self.path
@@path
end
class_method_proxy :path
def print_path
puts path
end
end
Of course you can pass multiple symbols to proxy many methods at the same time.
class_method_proxy :path, :another_path, :a_third_one
Sashimi: Just Received A Tasteful Update 0
Yesterday I announced Sashimi and now it's already time of tasteful updates.
Changes
First, thanks to all the people that appreciated my work. Second, new commands and options are avaliable for Sashimi.
Update all plugins in your repository:
$ sashimi update --all
Install a plugin to your Rails app:
$ sashimi install --rails click-to-globalize
NOTE this is an alias for the add command.
Update a plugin of a Rails app:
$ sashimi update --rails click-to-globalize
NOTE If your application is versioned with Svn or Git, Sashimi will automatically schedules for add/remove the added/removed files.
How To Update
$ (sudo) gem update jodosha-sashimi --source=http://gems.github.com
I hope you enjoy those addictional options.
Sashimi: A Rails Plugins Manager Gem 3
I have a really, really bad memory: each time I need to install a Rails plugin, I Google to find the repository, then try to download the code. Often, I remember the url, but the server is down. Damn!
All this annoying issues kill the Rails rapidity on application prototyping. But, what if all the plugins which I need are available offline on my notebook? I can forget about all that urls, and I should stop to worry about the server status.
To solve this problems, I wrote Sashimi, it's a gem that manages you favourite Rails plugins in a local repository.
How It Works?
First you need to install it with:
$ (sudo) gem install jodosha-sashimi --source=http://gems.github.comNow you can install a plugin on your local repository:
$ sashimi install git://github.com/jodosha/click-to-globalize.gitTa-daaaa!! Now Click to Globalize is available offline:
$ sashimi list
click-to-globalizeIf you need to add it to your Rails app, just move to your app root, then type:
$ sashimi add click-to-globalize
Conclusion
I found Sashimi really useful, I hope you too.
For the complete reference, please check out at the official gem page.
Ruby: XML Parsing With SAX 3
SAX is an event-driven parser for XML.
It sequentially reads the xml and generates special events. So, if you want to use SAX, you should implement the code to handle them. It's quite different from the DOM model, where the whole xml is parsed and loaded in an tree.As you can see, the first approach is more difficult than the DOM one. Why we should use it? Depends.
If you want to extract certain informations from a big file, probably you should choose a SAX implementation, in this way you can avoid the initial DOM loading overhead.
The Ruby XML Library
The Ruby core library has a built-in XML parser (both DOM and SAX) called REXML, but it's terribly slow, it's highly advisable to use libxml. It's a binding to the popular library from Gnome and it was released as gem.
The Ruby Implementation
In first instance we need an handler, to deal with the SAX events.
class Handler
def method_missing(method_name, *attributes, &block)
end
end
Libxml generates several events and it expects to find certain methods into the class assigned ad handler. With method_missing we simply avoid any exception.
A More Useful Example
We try to extract the most recent headlines of a blog.
Download the feed:
curl http://feeds.feedburner.com/LucaGuidi >> luca.xml
Now we need our custom SAX parser:
require 'rubygems'
require 'xml/libxml'
require 'handler'
class SaxParser
def initialize(xml)
@parser = XML::SaxParser.new
@parser.string = xml
@parser.callbacks = Handler.new
end
def parse
@parser.parse
@parser.callbacks.elements
end
end
We have just wrapped the SAX parser from libxml and we have registered our first class as callback handler.
Now we are going to improve the handler to recognize and save the post titles:
class Handler
attr_accessor :elements
def initialize
@elements = []
end
def on_start_element(element, attributes)
@print = true if element == 'title'
end
def on_characters(characters = '')
@elements << characters if @print
end
def on_end_element(element)
@print = false
end
# Handle all missing methods of the SAX events chain.
# You can implement or omit one or many of those methods, without any raising Exception.
#
# The complete chain is:
# on_start_document
# on_processing_instruction(instruction, arguments)
# on_start_element(element, attributes)
# on_characters(characters = '')
# on_end_element(element)
# on_end_document
def method_missing(method_name, *attributes, &block)
end
end
When the handler is instantiated we create an internal array to store our results, then when we find and title element we set on true the print flag. When it's true we can store the data into elements, then we set on false on the ending handler of the element.
Usage
We create a trivial script:
#!/usr/bin/env ruby
require 'sax_parser'
xml = open(ARGV[0], 'r').collect { |l| l }.join
puts SaxParser.new(xml).parse
From the shell:
./parse luca.xml
Conclusion
SAX is less elegant and easy than DOM, but could be very useful in certain cases.
Ruby: How To Avoid A respond_to? Call 0
I'm writing this post as contribution to the Campagna Anti-IF (Anti-IF Campaign).
Problem
I'm developing an internal Rails plugin for widgets, it provides a class called Widget (really unconventional :-P), and each widget should inherit from it.
The actual implementation provides a callback called before_render, that allows to add some logic to a widget, if implemented it's called before the widget rendering.
Ruby doesn't have abstract methods, so I have to check if the subclass has the implementation of mentioned method:
# Rendering code..
before_render if respond_to? :before_render
# ...
As you can see it's an inefficient and inelegant way to render the widget, cause we always check if the method was implemented, and because I have introduced an if statement.
Solution
I added to Widget an empty before_render method: if the method it wasn't implemented into the subclass the rendering code will be safely called.
Here the new code:
def before_render
end
# Rendering code..
before_render
# ...
Ruby: Read A File With One Line Of Code 3
This snippet shows how to read a file and puts all the lines into an array.
f = *open('file.txt').map {|l| l.rstrip}
# => ["Hi, from the", "txt file."]
Explanation
The open method returns an IO object, that include the Enumerable module, now we can just use #map (or #collect).
The splat operator is only a sugar syntactical shortcut for map
.Ruby: How to check the operating system 0
Today I'm finishing the code cleanup for my latest Rails plugin (will be soon released) and I want to execute some rake tasks, only if the OS supports certain system calls.
The following snippet helps to check the current platform.
# (c) 2007 Luca Guidi (www.lucaguidi.com) - Released under MIT License.
# This code was inspired by Prototype rake test tasks.
require 'webrick'
class OperatingSystem
class << self
def host
Config::CONFIG['host']
end
def macos?
host.include?('darwin')
end
def linux?
host.include?('linux')
end
def windows?
host.include?('mswin')
end
def current
case
when macos?: 'macos'
when linux?: 'linux'
when windows?: 'windows'
else 'unknown'
end
end
end
end
Play random files with Ruby 0
It will search recursively for all readable files, starting from execution from the folder passed as argument or, if miss, from current folder. Tested on a linux box with mplayer.
Usage:
$ ./shuffle
# play recursively all files from current folder
$ ./shuffle /path/to/files
# play recursively all files from specified folderThat's the source code.
#!/usr/bin/ruby
player = "/usr/local/bin/mplayer"
formats = ["mp3", "ogg", "flv"]
folder = ARGV[0] || ""
class ShufflePlayer
@files
@frx
@player
def initialize(player, formats, folder)
@player = player
gen_regex(formats)
load_files(folder)
end
def play
flag = 1
while flag && @files.length > 0
flag = system("#{@player} -quiet #{@files.delete(@files[rand(Time.now) % @files.length])}")
end
end
private
def load_files(folder)
@files = Dir[folder+'**/*.*'].reject!{|f| f if @frx.match(f).nil? || !File.readable?(f) }
@files.collect!{|f| f.gsub(/['"\-\s\[\]\(\)]/){ |m| "\\"+m }} unless @files.nil?
end
def gen_regex(formats)
@frx = /(#{formats.join('|')})$/
end
end
ShufflePlayer.new(player,formats,folder).playSecurity disclaimer: this code is strong insecure, i've posted for study purpouses, I'm not responsable if someone use it to attack your system.
