Posts tagged with 'gem':

Announcing Coloration, editor color scheme converter


Without further ado I'm introducing Coloration - editor/IDE color scheme converter. It is an evolution of tm2jed tool and at the moment it can convert Textmate color themes (in XML plist format) to Vim, JEdit and Kate/KWrite/KDevelop color schemes. So if you are Textmate->Vim convert or you just envy Textmate users for their good looking, dark themes now you have no excuse to not try out Coloration.

Here's how Vim with Sunburst theme looks like:

Vim with Sunburst color scheme

If you want to give Coloration a try you have two options. Either you can use online version at coloration.sickill.net or you can install ruby gem coloration:

gem install coloration

It will give you tm2vim, tm2jedit and tm2katepart commands. Note it requires ruby 1.9.

Let me know if you find it useful. Source code is available at github.com/sickill/coloration.

Enjoy!

View Comments

Thoughts on Ruby gem dependencies


The problem

Having gem bundler is great. First, you can forget about gem version collisions (damn you activation errors!). Second, you can forget about manually installing gems on all your machines. Third, you can use git repositories and local directories as gem sources which is neat and is invaluable when working on your own gems. But bundler is a workaround. Yes, it's a workaround for poor rubygems design. Let's look at few examples of the problems I've noticed.

I'll start with dm-paperclip gem. Recently I was porting my Merb app to Rails 3 and I've encountered few problems with this little sucker. The biggest headache I had with validations. Note it was fixed recently in dm-paperclip, but makes good example of problem that still exists in relation to other gems. dm-paperclip was doing this:

...
unless defined?(DataMapper::Validate).nil?
...

What's the problem here? Let's say you have following lines in your Gemfile:

gem "dm-validations"
gem "dm-paperclip"

Looks like everything should work. Wrong! Rails 3 requires all the gems from your Gemfile by calling Bundler.require Rails.env but Bundler.require doesn't use order of gems specified in Gemfile. For me it first required dm-paperclip and then dm-validations, so when dm-paperclip was being required DataMapper::Validate wasn't defined yet. I heard that it may change in future and Bundler will respect the order, to some degree of course. Does this problem lay in bundler or in dm-paperclip? In none of them. Bundler doesn't know about "optional" dependencies of dm-paperclip and dm-paperclip has no way to tell us/bundler it can benefit from some optional lib.

Anyway, this is good example why explicit requiring of gems seems better in this scenario. By adding require "this" and require "that" in places where you actually need it you're breaking DRY principle (you already have it in Gemfile) but you can have perfect control of the order. This way you can solve above dm-paperclip problem. And by using explicit requires you can move your app away from bundler (to i.e. rip or Isolate) if you want to and you don't need to add these requires because they're already in the app. But why would you need to think about gem require order in your Rails app? You shouldn't think about it. And you don't always know what are optional libraries for the gems you're using.

Let's look at second issue. Multiple markdown processing libraries. There's BlueCloth, Maruku, Kramdown, RDiscount, rpeg-markdown and some more. All of them are doing the same thing but the difference is mainly in performance. BlueCloth and Maruku are pure ruby libraries, RDiscount and rpeg-markdown are bindings to fast C libraries. But they all have the same interface:

BlueCloth.new(markdown_string).to_html          # bluecloth
Maruku.new(markdown_string).to_html             # maruku
Kramdown::Document.new(markdown_string).to_html # kramdown
RDiscount.new(markdown_string).to_html          # rdiscount
Markdown.new(markdown_string).to_html           # rpeg-markdown

Now, if gem A depends on Maruku and gem B depends on RDiscount I'll have two markdown libraries with identical interface required in my app. I know that RDiscount is faster because it's C and I'd like all of my app's functionalities to use it but gem A will use slower Maruku. Sad but true.

Third rubygems issue is something in the middle between dm-paperclip+bundler problem and markdown problem. Devise, "Flexible authentication solution for Rails with Warden" supports many ORMs (ActiveRecord, DataMapper, Mongoid). Now, all code related to integration with mentioned ORMs is included in devise itself. Devise checks which ORM is available at runtime (like in dm-paperclip example) and requires appropriate file choosing from many available alternatives (like in markdown example). It's far from being perfect. How this could be improved?

It'd be probably better to put integration code in separate gems. This way people involved in development of ORMs could work on integration without access to Devise repository. Yeah, I know, it's not a big deal on github, just fork and send pull request. But it worked really well for dm-rails. DataMapper guys were more interested in getting DM work under Rails 3 than Rails developers and they definitely knew more about DM specifics. They provide the gem and everyone is happy. But if there were many gems providing this functionality for Devise then user would be responsible for installing it. There's better solution on my mind though, read on.

Possible solutions

To solve first mentioned issue let's just add optional dependencies to rubygems. It could work in following way.

Gem author specifies list of optional dependencies:

Gem::Specification.new do |s|
  ...
  s.optional_dependency "nokogiri", "for tidying output"
  s.optional_dependency "bar", "for bar support"
end

You are installing the gem:

$ gem install foo
Installed foo.
Optional dependencies for foo:
- nokogiri (for tidying output)
- bar (for bar support)

Or you could install it with optional deps:

$ gem install foo --with-optional-deps
Installed nokogiri.
Installed bar.
Installed foo.

Benefits of having explicit optional deps would be:

  • user could see what are the optionals and decide if he wants them
  • automatic tools like bundler could be configured to install optional deps, either for all gems or for specific ones
  • bundler could require optional gems before the one which "optionally" depends on them, solving require order issues

To solve second and third issue we can add "provider gems". What's that? Decent Linux package managers like Archlinux's pacman allows you to specify that the package provides the same functionality and the same interface as the other one. In rubygems it could look like this:

Gem authors of all mentioned markdown processors could specify that their gem provides "markdown":

Gem::Specification.new do |s|
  ...
  s.provides "markdown"
  ...
end

Additionally they would need to provide unified interface, in this case simple Markdown = RDiscount should do the trick.

Now, you as gem user could use it like this:

require "markdown"
Markdown.new(markdown_string).to_html

This way gem A and B can depend on "markdown", and you decide which one you want to install. gem install A or bundle install in this case could show you this:

$ gem install A
Gem "A" depends on "markdown". Please select provider gem from following alternatives:
1. BlueCloth
2. Maruku
3. ....

Of course having two "markdown providers" with the same interface (note that require "markdown" is also part of the interface) would be impossible in the same gem environment but this can easily be solved by using Bundler, Isolate or awesome rvm's gemsets. Only problem I see here is when one gem depends on "maruku", not on "markdown", another gem depends on "rdiscount", and your app depends on both of these gems... yuck.

"Provider gems" can be easily applied to Devise's case:

Gem::Specification.new do |s|
  s.name "devise"
  s.dependency "devise-orm-proxy"
  ...
end

Gem::Specification.new do |s|
  s.name "devise-orm-mongoid"
  s.provides "devise-orm-proxy"
  ...
end

Gem::Specification.new do |s|
  s.name "devise-orm-dm"
  s.provides "devise-orm-proxy"
  ...
end

Another example why "provider gems" can be good idea is extlib / AS collision. For example dm-paperclip depends on extlib because it needs inflector. But you can't easily use it in Rails 3 app at the moment because AS+extlib = "UsersesController" :) dm-core used to use extlib for inflections and has been recently converted to AS for some reasons.

"Provider gems" can solve also this problem. Look at this:

Gem::Specification.new do |s|
  s.name "dm-core"
  s.dependency "inflector"
  ...
end

Gem::Specification.new do |s|
  s.name "dm-paperclip"
  s.dependency "inflector"
  ...
end

Gem::Specification.new do |s|
  s.name "extlib"
  s.provides "..."
  s.provides "inflector"
  s.provides "..."
end

Gem::Specification.new do |s|
  s.name "activesupport"
  s.provides "..."
  s.provides "inflector"
  s.provides "..."
end

Conclusion

I realize that these proposed solutions are not ideal and there are some edge cases which need some more thought but maybe it will become a good start for further discussion about the problem. Rubygems code is on github now so we can fork it and improve it!

View Comments

LessCSS goodies


If you haven’t heard about LessCSS then check it out, really cool solution for writing css code in concise way. I’m planning to use it in some of my projects (and probably for this blog’s styles) and I’ve created two tools which could ease my work with LessCSS.

First tool, css2less, is CSS-to-LessCSS converter. Of course it can’t use all of LessCSS features because only programmer knows where to use variables and other stuff properly for specific project. However what it can do is to find all rules that can be nested and outputs them for given css file.

Grab it from github and use like that:

ruby css2less.rb my.css > my.less

You will get .less file with all styles from original .css file but with nested rules notation. It’s a good start for further tweaking, ie adding variables.

Second tool, rack-lesscss, is a Rack middleware which converts .less files into .css files on the fly during request. It’s main purpose is to ease development stage when you change your .less files frequently. With rack-lesscss middleware enabled you don’t need to compile .less files by hand after every change. LessCSS compiler has an option to watch for changes in .less file and automatically recompiles it but you need to remember to run compiler in watch mode for every stylesheet every time you start development session. There are also at least two Rails plugins which nicely integrates LessCSS into the app but this middleware can be used with Rails as well as with other ruby web frameworks like Merb or Sinatra.

Install gem:

sudo gem install --source http://gems.github.com sickill-rack-lesscss

or grab it from github.

Enable by adding following to your rackup file (config.ru, or config/rack.rb in Merb app):

require 'rack-lesscss'
use Rack::LessCss, :less_path => File.join(APP_ROOT, "public", "css"), :css_route => "/css"

Above code will enable on-the-fly .less files compilation for all requests matching /css/*.css.

It accepts two arguments:

  • :less_path – directory where source .less files are stored (required)
  • :css_route – route which this middleware will handle (optional, default is /stylesheets)

And don’t use it on production for obvious reason :) It’s meant to be used for development only.

View Comments

Rack middleware showing git or svn revision


Rack is fun. Really, lots of fun. After creating middleware for showing markup errors and viewing several presentations related to Rack I was thinking about Rack’s potential. And it’s big. The result of my thinking (and a little coding) is another middleware.

When you deploy application to a demo server QA (or client) wants to know which revision is currently running. Of course you can handle it in a old-school way putting some helper into your layout(s) which will obtain revision number exec’ing “svnversion” or sth like this. It works but it’s not the most elegant solution. First, you are including code related only to demo/staging server in layouts/helpers (production server and your development box don’t need it at all). Second, you probably do this for every new project. But all ruby web frameworks now run on Rack so better solution would be to move revision-displaying code from the app itself to the middleware. So here comes RevisionInfo.

Install:

gem install sickill-rack_revision_info --source http://gems.github.com

Enable in Merb:

config/dependencies.rb:

dependency "sickill-rack_revision_info", :require_as => "rack_revision_info"

config/rack.rb (before line with run Merb::Rack::Application.new):

use Rack::RevisionInfo, :path => Merb.root

Enable in Rails:

config/environment.rb:

config.gem "sickill-rack_revision_info", :lib => "rack_revision_info", :source => "http://gems.github.com"
config.middleware.use "Rack::RevisionInfo", :path => RAILS_ROOT

Enabling this middleware for svn managed application you will get <!-- Revision 666 (2009-05-28 19:00:25 +00:00) --> appended to the end of resulting html. For git repository it will be <!-- Revision 31d0fa132584c7e9bf978443052b545c1aeca96b (2009-05-28 19:00:25 +00:00) -->. It’s commented out so in order to see it look into page source.

However if you prefer to see revision number somewhere on the page you can specify CSS selector of page element and method of injection like this:

use Rack::RevisionInfo, :path => Merb.root, :inner_html => ".footer li.revision"

Here are available injection methods:

  • :append => "div.footer" inserts revision info at the end of footer div content
    <div class="footer"><img...> Revision 666 (2009-05-28 19:00:25 +00:00)</div>
  • :prepend => "div.footer" inserts revision info at the begining of footer div
    <div class="footer">Revision 666 (2009-05-28 19:00:25 +00:00) <img...></div>
  • :after => "div.footer" inserts revision info after footer div
    <div class="footer"><img...></div>Revision 666 (2009-05-28 19:00:25 +00:00)
  • :before => "div.footer" inserts revision info before footer div
    Revision 666 (2009-05-28 19:00:25 +00:00)<div class="footer"><img...></div>
  • :inner_html => "div.footer" replaces footer div content with revision info
    <div class="footer">Revision 666 (2009-05-28 19:00:25 +00:00)</div>
  • :swap => "div.footer" replaces whole footer div with revision info
    Revision 666 (2009-05-28 19:00:25 +00:00)

If you enable injection using one of above methods you need to have Hpricot gem installed because HTML manipulation is done using it (if you don’t use injection – only comment appending – you don’t need hpricot). Specified CSS selector can be any selector supported by hpricot so you can freely use funky stuff like #main ul.footer li:last. You can also use XPath like //div/ul/li.

Sources (as usual) are available on github.com. Enjoy!

View Comments

Rainbow gem updated for Ruby 1.9.1


Thanks to Chad from Spicycode my rainbow gem now supports Ruby 1.9.1 (and it’s backwards compatible with Ruby 1.8.x). It doesn’t provide any new features so there is no need for upgrade for Ruby 1.8.x users. I’ve released new version 1.0.2 at rubyforge.

View Comments

Colorizing console output with Rainbow ruby gem


If you’re working on some cool ruby console-based application or just want to add a little style to your script here is a nice gem for you. It’s called Rainbow and it extends ruby String class adding methods to wrap the string with ANSI escape codes.

Look at example irb session and see example usage:

Rainbow adds following methods to String class:

  • foreground(color) (with color and colour aliases)
  • background(color)
  • reset
  • bright
  • italic (not well supported by terminal emulators).
  • underline
  • blink
  • inverse
  • hide.

Color can be one of following symbols: :black, :red, :green, :yellow, :blue, :magenta, :cyan, :white and :default.

Each of those methods returns string wrapped with some ANSI codes so you can chain calls as in example above.

It also has Windows support (uses win32console gem if installed, otherwise strings are returned unaltered).

The gem is on rubyforge.org so install it by:

sudo gem install rainbow

and require it in your script.

The sources are on github, as usual.

Note: I know that there is similar gem on rubyforge called colored_. But, first, it adds too many methods to String class (the Rails way, method per color + method per background color + method per foregroundbackground color…). Second, as I had it already implemented creating a gem from this code was a snap, so why not do it?

View Comments