Posts tagged with 'merb':

Rails-like console for any Rack based ruby web app


I always miss script/console from Rails while developing my Sinatra apps, especially ones built with DataMapper where I need to auto-migrate my db. Sinatra doesn't come with any comparable solution as it's not a full framework, but rather library for creating simple web apps. Recently I tried Heroku platform and their "heroku console" command inspired me to create something similar - racksh aka Rack::Shell.

racksh is a console for Rack based ruby web applications. It's like Rails' script/console or Merb's merb -i, but for any app built on Rack. You can use it to load application environment for Rails, Merb, Sinatra, Camping, Ramaze or your own framework provided there is config.ru file in app's root directory.

It's purpose is to allow developer to introspect his application and/or make some initial setup, ie. running mentioned DataMapper.auto_migrate!. It's mainly aimed at apps that don't have similar facility (like Sinatra) but can be used without problems with Merb or Rails apps.

How it works? It loads whole application environment like Rack web server, but it doesn't run the app. Simply, methods like use or run which are normally invoked on Rack::Builder instance are being stubbed.

Instalation is as easy as:

gem install racksh -s http://gemcutter.org

Then to open console run following inside rack application directory (containing config.ru file):

racksh

To specify location of config.ru set CONFIG_RU env variable:

CONFIG_RU=~/projects/foobar/config.ru racksh

Executing ruby code inside application environment and printing results is also supported:

racksh Order.all
racksh "Order.first :created_at => Date.today"

Default Rack environment is set to development but it can be changed by setting RACK_ENV env variable:

RACK_ENV=production racksh

Now I don't need to create some kind of console.rb for my new Rack app, I just use racksh. Enjoy!

UPDATE: Read here for more info.

View Comments

Subdomain shared cookies in Merb's specs


I’m currently working on Merb app which makes use of subdomains for user accounts. In order to have user authenticated on both base domain and subdomains I set cookie domain like this in init.rb:

 Merb::Config.use do |c|
    c[:default_cookie_domain] = ".mydomain.com"
  end

Dot at the start of domain name specifies that the cookie will be set for “mydomain.com” and all its subdomains. This works perfectly in browser(s) but I’ve encountered a problem in my request specs. After authenticating at “mydomain.com” app redirects to “username.mydomain.com”. But next request to either “mydomain.com” or “username.mydomain.com” shows that session is no longer authenticated. After some reading through merb-core sources I’ve found that Merb::Test::Cookie can’t properly handle cookies with domain set to ‘.foo.com’ (with dot at the start).

This is because Merb::Test::Cookie#valid? makes some regexp check comparing current request domain with domain from cookie, which fails for cookie domain set to ‘.foo.com’. I’ve created a fix and spec for this scenario. Patch can be found in this commit.

Until it gets merged and released with new Merb version (I hope in 1.1) It was already merged into Merb master branch, but until the 1.1 release the simplest workaround is to monkey patch Merb::Test::Cookie class, ie. in spec_helper.rb like this:

class Merb::Test::Cookie
  def valid?(uri)
    domain_ = domain.start_with?('.') ? domain[1..-1] : domain
    uri_path = uri.path.blank? ? "/" : uri.path
    uri.host =~ Regexp.new("#{Regexp.escape(domain_)}$") &&
    uri_path =~ Regexp.new("^#{Regexp.escape(path)}")
  end
end
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