Merb *is* Rails

Posted by ezmobius Tue, 23 Dec 2008 18:21:00 GMT

Wow this has been a hectic, emotional week. The Rails and Merb core teams have been silently working together towards this monumental announcement. The announcement is that Merb is Rails and Rails is Merb.

Merb and Rails are joining forces and merging the two code bases for Rails-3.0. We’re targeting RailsConf for the first cut of this magic.

When I first started merb way back in the day it was just a fun little project to hack on. But it became more serious as I explored the options. I always considered merb-core a clean room rewrite of ActionPack and I think this tended to upset some people who were very attached to rails.

Fast forward to current day and Merb-1.0 has been out for a while and there is a whole brouhaha of Rails VS Merb memes on the twitters and blogs. This has to stop as it is tearing apart the community and is very non productive.

So our two teams started talking to see if we could put our differences aside and come together for the common good. We’ve laid out a roadmap of what and how to integrate merb’s best features into rails-3.0. I think we have a great plan that will make Rails the best framework in existence. It will be a blend of the best things we have discovered while working on merb, while keeping the Rails aesthetic people have grown to love.

You can expect to get a kick ass, fast, memory efficient version of rails(merb) this spring!

Merb folks will not be left out in the cold. We will continue to support bug and security fixes for the merb 1.0.x line. And we will provide a clear upgrade path to Rails 3.0 for merb apps. We still have quite a few merb apps running internally at ey and will want an upgrade path for our own apps as well.

This is going to be a lot of work for everyone involved but in the end I think this may just be the most inspiring open source story in history.

I’m so impressed with everyone involved. All the core team members from both sides have been able to put away the weapons and egos and really come together, committed to making this transition work seamlessly.

2009 is going to be a seriously strong year for the ruby community. With everyone working together, we have such a kick ass team of smart people that this whole framework thing is going to be a solved issue.

Merb is dead, long live Merb(Rails-3.0)!



http://rubyonrails.org/merb
http://weblog.rubyonrails.org/2008/12/23/merb-gets-merged-into-rails-3
http://yehudakatz.com/2008/12/23/rails-and-merb-merge/

Tags , ,  | 65 comments

Does it have to be a competition between Rails and Merb?

Posted by ezmobius Wed, 21 May 2008 20:12:00 GMT

It seems like a lot of folks out there want there to be a battle royal between Merb and Rails. I just wanted to dispel this myth.

Merb was written because it scratched an itch that I and many of my hosting customers had, mainly memory footprint, speed, concurrent requests and simple maintainable code. This does not mean that Merb has to be thought of as a Rails competitor. Merb stands on its own merits just as Rails does.

I feel that both of these frameworks have great strengths and weaknesses and that they compliment each other in many ways. Face it Merb would never be around if Rails had not come first. And I see Merb as a great experimentation playground for exploring web framework functionality while learning a great many things from Rails and building a fresh view based on Rails strengths and weaknesses.

There is no reason that a lot of the goodness in Merb cannot be applied back to Rails, but it is no small feat to trim down rails size without breaking backwards compatibility.

I view it like this, more choices make the Ruby ecosystem a better place. So let’s just stop with the Rails VS Merb stuff. How about people choose what framework they want to use based on the frameworks merits and features rather then religious arguments about how my framework can beat up your framework.

The Ruby community in general has been exceedingly nice as long as I have been a part of it. I wrote Merb for a reason, if Merb’s philosophies agree with your tastes then great, use Merb. If Rails is your thing then that’s great too! We do not need a monoculture.

Rails has been Ruby’s killer app and has brought Ruby to the masses. But Ruby is growing up, there are many alternate Ruby implementations now and they all work together for the common good of Ruby.

I’d like the same thing to happen with Rails, Merb and all the other ruby web frameworks. Let’s all work together to make the Ruby ecosystem stronger. We do not need to fight amongst ourselves when there are plenty of other Programming language communities to fight with :P

I guess what I am saying is that I see the proliferation of ruby web frameworks as a sign that Ruby itself has “arrived” and is here to stay. So can’t we all just get along in Ruby web framework land?

Tags ,  | 33 comments

Speaking at Seattle on Rails Tomorrow

Posted by ezmobius Tue, 13 Feb 2007 06:10:00 GMT

Just a quick note to mention that I am giving a talk titled “Exploring the Request/Response Life-Cycle through Mongrel and the Rails Source Code.”

This will be on Feb 13th at 6 pm and the Greenlake public library. If you live near Seattle then you should show up ;)

I will be posting my slides after the talk tomorrow and hopefully the audio gets recorded as well.

More info here: http://www.seattleonrails.org/

Tags , ,  | 5 comments

Speed up page loads

Posted by ezmobius Fri, 29 Dec 2006 23:51:00 GMT

Here is a little tip that can drastically speed up your page loads for pages that have a lot of static assets. Especially for pages with tons of little images.

Most browsers will only open up 2 concurrent connections per cname. this means that if all of your assets are being served from http://example.com and you have a lot of little images and scripts on the page, the clients browser will only open two connections to example.com and pipeline or use those two connections to download all the assets on the page.

By using a wildcard subdomain or manually setting dns so that you spread out the static assets over a few different subdomains, you let the browser open two connections per subdomain so all the assets will download in a more parallel fashion. This can be the difference between your page loads lagging at the end while they load up all the little assets and having the page snap into place and seem a lot quicker to the user.

So if we use a simple little view helper method for all of our image urls we can spread the load out by faking the browser into thinking it is connecting to multiple servers. For example if we serve all our images from these subdomains:

asset1.example.com
asset2.example.com
asset3.example.com
asset4.example.com

This will give us 8 concurrent connections from the browser to the server for static assets which dramatically decreases page load time. The thing to watch out for is that you always want to serve the same asset from the same subdomain or else you defeat browser caching and won’t gain anything from this trick. So we will use an Zlib hash of the asset url modulo 4 to choose a subdomain. Here is a simple helper:

require 'zlib'

  # balance images across many domains to force the opening of more connections  
  # updated to use Zlib.crc32 instead of md5 as per
  # comment from David
  def balanced_asset_url(asset)        
    idx = (Zlib.crc32(asset || "error" ) % 4) + 1
    %!http://asset#{idx}.#{request.domain}#{asset}!
  end

Then use it like this:

<%= image_tag balanced_asset_url('/images/foo.png') %>

By hashing the asset path we make sure that each time this helper is called for the same asset it will always return the same subdomain.

This technique is most useful when you have many objects on a page that need to make an additional http request each to render. By tricking the browser into making more concurrent connections when fetching assets we can speed up our page load times and make our sites seem more ‘snappy’

I’m sure you could make this into a nice little plugin or integrate it into the normal image_tag helper if you so desired. This is just an illustration.

Tags  | 15 comments

RailsConf Talk Suggestions?

Posted by ezmobius Wed, 19 Apr 2006 19:27:00 GMT

I will be speaking about Rails Deployment amongst other things during my talk at RailsCONf this June in Chicago. I wanted to open up a discussion here about what the audience would like to have me cover.

So this is your chance to let me know what topics or issues you would like to hear about. Mostly the talk will cover deployment issues and server setups and whatnot. But I do have a few tricks up my sleeve as well ;)

So tell me what you want me to talk about in the comments and you can help shape my presentation!

Tags , , , , , , ,  | 8 comments

Rails Workshop For Good

Posted by ezmobius Mon, 10 Apr 2006 04:28:00 GMT

I’m proud to announce the Workshop For Good Rails class I am teaching.
http://www.workshopforgood.org

It is a two day intensive workshop teaching Ruby on Rails. I will be teaching it along with Jeff Casimir and Amy Hoy of slash7 fame.

The workshop will take place Saturday, May 20th and Sunday, May 21st from 9AM to 5PM. All activities will take place at the César Chávez Public Charter High School Capitol Hill campus at 709 12th Street SE, Washington, DC, 20003.

This workshop is cool because all proceeds go to benefit the César Chávez Public Charter School. This is an underfunded public high school in DC.

I am donating my time to teach the class because I believe in helping out where I can. The two day workshop is only $400($200 for students) So it is a bit cheaper then other rails workshops I see going on. If you can make it to DC in late May please do. The class is targeted at beginner/intermediate Railers. But I promise to cover whatever you want to see if you are already more advanced with rails.

This is a great cause so please people, link to this site or blog about it a bit would you? I would love to sell out and give this high school as much funds as we can ;-)


http://www.workshopforgood.org

Tags , ,  | 2 comments

My RailsConf talk proposal was accepted!!

Posted by ezmobius Thu, 16 Mar 2006 23:47:00 GMT

So I just found out that my talk proposal to speak at the First Internationl RailsConf was accepted!

I am totally stoked and honored that I was chosen. There were a ton of talk proposals to go through to come up with a final decision and I am very happy to say that I made the final cut.

My talk will be about rails deployment. And I hope to have the beta release of my Rails Deployment book released in pdf form before RailsConf.

Thanks to the organizers of RailsConf and a deep thanks for letting me speak. This event will go down in history as rails mindshare grows and grows. It’s been an exciting ride on the rails for me. I stumbled upon rails when I was trying to decide whether to learn python or ruby as a step up from PHP. The original screencast sealed my fate and the last 19 months on rails has been an eye opener to say the least.


I will see you all at RailsConf and look forward to putting faces to all the names of folks I know from irc or the rails and ruby-talk mailing lists and all the other railsers I only know from cyberspace.


irb(main):003:0> Ezra.respond_to? :stoked
=> true

Tags , , , , , , ,  | 6 comments

The Book.

Posted by ezmobius Mon, 30 Jan 2006 23:44:00 GMT

So I have been very busy with all my jobs and projects, especially the book. It is coming along well though. I am still on target to get a beta release in late March so stay tuned.

Sorry i haven’t been updating my blog much but I have been otherwise involved. Hopefully I won’t let it go so long between posts.

Tags , , , , ,  | 10 comments

New ez_where plugin.

Posted by ezmobius Mon, 30 Jan 2006 23:31:00 GMT

So me and my friend Fabien Franzen have been busy creating the new ez_where plugin. It's been totally revamped with many additions to the ease of use and the syntax.

Big thanks to Fabien for his excellent work extending my original idea and forcing me to rethink this stuf to make it better. Hope someone finds it usefull. As always, this is alpha software so let me knwo of any bugs or any questions you might have.

We have added the ability to do sub queries and nested AND's and OR's. Plus we have replaced find_with_conditions with the shorter ez_find. This method takes a block and can use the :include options to search on multiple models and return them all in one query with your associations included.

These new changes break backwards compatibility, but I think they are worth it. So if you are using the old version of this plugin be ready to refactor a bit ;-). Without further ado, here is the massive README from the distribution.

You can get this version at: opensvn.csie.org/ezra/rails/plugins/dev/ez_where/


Welcome to the new improved ez_where plugin for rails. This plugin is meant 
to be used as a nice ruby like syntax for creating the :conditions part of an 
ActiveRecord::Base.find. We also add the ActiveRecord::Base.ez_find method.
This method takes a block to simplify single and multi table queries.

articles = Article.ez_find(:all, :include => :author) do |article, author|
  article.title =~ "%Foo Title%"
  author.any do
    name == 'Ezra'
    name == 'Fab'
  end 
end

This will produce :conditions => ["article.title LIKE ? AND 
                   (authors.name = ? OR authors.name = ?)",
                   "%Foo Title%", "Ezra", "Fab"]

Basically here is the breakdown of how we map ruby operators 
to SQL operators:

foo == 'bar'           #=> ["foo = ?", 'bar']
foo =~ '%bar'          #=> ["foo LIKE ?", '%bar']
foo <=> (1..5)         #=> ["foo BETWEEN ? AND ?", 1, 5]
id === [1, 2, 3, 5, 8] #=> ["id IN(?)", [1, 2, 3, 5, 8]]
<, >, >=, <= et all will just work like you expect.

There is also the ability to create the conditions in stages so 
you can build up a query:

cond = Caboose::EZ::Condition.new do
  foo == 'bar'
  baz <=> (1..5)
  id === [1, 2, 3, 5, 8]
end
 
@result = Model.find(:all, :conditions=> cond.to_sql)
#=> ["foo = ? AND baz BETWEEN ? AND ? AND id IN (?)",
     "bar", 1, 5, [1, 2, 3, 5, 8]]

You can even do nested sub conditions. condition will use AND 
by default in the sub condition:

cond = Caboose::EZ::Condition.new :my_table do
  foo == 'bar'
  baz <=> (1..5)
  id === [1, 2, 3, 5, 8]
  condition :my_other_table do
    fiz =~ '%faz%'
  end
end

@result = Model.find(:all, :conditions=> cond.to_sql)
#=> ["my_table.foo = ? AND my_table.baz BETWEEN ? AND ? 
     AND my_table.id IN (?) AND (my_other_table.fiz LIKE ?)",
     "bar", 1, 5, [1, 2, 3, 5, 8], "%faz%"]

You can also build multiple Condition objects and join
them together for one monster find:

cond_a = Caboose::EZ::Condition.new :my_table do
  foo == 'bar'
  condition :my_other_table do
    id === [1, 3, 8]
    foo == 'other bar'
    fiz =~ '%faz%'
  end
end
#=> ["my_table.foo = ? AND (my_other_table.id IN (?) AND my_other_table.foo = ?
       AND my_other_table.fiz LIKE ?)", "bar", [1, 3, 8], "other bar", "%faz%"]

cond_b = Caboose::EZ::Condition.new :my_table do
  active == true
  archived == false
end

#=> ["my_table.active = ? AND my_table.archived = ?", true, false]

composed_cond = Caboose::EZ::Condition.new
composed_cond << cond_a
composed_cond << cond_b
composed_cond << 'fuzz IS NULL'

@result = Model.find(:all, :conditions => composed_cond.to_sql)
#=> ["(my_table.foo = ? AND (my_other_table.id IN (?) AND my_other_table.foo = ? 
      AND my_other_table.fiz LIKE ?)) AND (my_table.active = ? AND my_table.archived = ?)
      AND fuzz IS NULL", "bar", [1, 3, 8], "other bar", "%faz%", true, false]   

You can compose a new condition from different sources:

ar_instance = Author.find(1)

other_cond = Caboose::EZ::Condition.new :my_table do 
  foo == 'bar'; baz == 'buzz'
end

cond = Caboose::EZ::Condition.new
# another Condition
cond.append other_cond
# an array in AR condition format
cond.append ['baz = ? AND bar IS NOT NULL', 'fuzz'], :or
# a raw SQL string
cond.append 'biz IS NULL'
# an Active Record instance from DB or as Value Object
cond.append ar_instance

#(append is aliased to << because of syntax issues 
involving multiple args like :or)

@result = Model.find(:all, :conditions=> cond.to_sql)

#=> ["(my_table.foo = ? AND my_table.baz = ?) OR (baz = ? AND bar IS NOT NULL) 
      AND biz IS NULL AND authors.id = ?", "bar", "buzz", "fuzz", 1]

OK there is also other options for doing subconditions. OR is 
aliased to any and any creates a subcondition that uses OR to 
join the sub conditions:

cond = Caboose::EZ::Condition.new :my_table do
  foo == 'bar'
  any :my_other_table do
    baz === ['fizz', 'fuzz']
    biz == 'boz'
  end
end

@result = Model.find(:all, :conditions=> cond.to_sql)

#=> ["my_table.foo = ? AND (my_other_table.baz IN (?) 
     OR my_other_table.biz = ?)",
     "bar", ["fizz", "fuzz"], "boz"]

OK lets look a bit more at ez_find with a few more complex queries:

# all articles written by Ezra. Here you can use a normal AR object
# in the conditions
# session[:user_id] = 2
ezra = Author.find(session[:user_id])    
@articles = Article.ez_find(:all, :include => :author) do |article, author|
  author << ezra # use AR instance to add condition; uses PK value if set: author.id = ezra.id
end 
#=>["(authors.id = ?)", 2]

# all articles written by Ezra, where he himself responds in comments
@articles = Article.ez_find(:all, :include => [:author, :comments]) do |article, author, comment|
  article.author_id == ezra.id
  comment.author_id == ezra.id   
end
#=>["(articles.author_id = ?) AND (comments.author_id = ?)", 2, 2]

# any articles written by Fab or Ezra
@articles = Article.ez_find(:all, :include => :author) do |article, author|
  author.name === ['Fab', 'Ezra']   
end
#=>["(authors.name IN (?))", ["Fab", "Ezra"]]

# any articles written by Fab or Ezra, using subcondition
@articles = Article.ez_find(:all, :include => :author) do |article, author|
  author.any do
    name == 'Ezra'
    name == 'Fab'
  end  
end
#=>["(authors.name = ? OR authors.name = ?)", "Ezra", "Fab"]

# any articles written by or commented on by Fab, using subcondition
@articles = Article.ez_find(:all, :include => [:author, :comments]) do |article, author, comment|
  article.sub { author_id == 1 }
  comment.outer = :or # set :outer for the comment condition, since it defaults to :and
  comment.sub { author_id == 1 }       
end
#=>["(articles.author_id = ?) OR (comments.author_id = ?)", 1, 1]

@articles = Article.ez_find(:all, :include => [:author, :comments],
                           :outer => { :comments => :or }, 
                           :inner => { :article => :or}) do |article, author, comment|
  article.sub { author_id == 1; author_id == 2 }
  comment.sub { author_id == 1 } 
end
["(articles.author_id = ? OR articles.author_id = ?) OR (comments.author_id = ?)", 1, 2, 1]

And finally you can use any and all with ez_condition like this:

cond = Article.ez_condition { active == true; archived == false }
cond.all { body =~ '%intro%'; body =~ '%demo%' }
cond.any { title =~ '%article%'; title =~ '%first%' }

#=>  ["articles.active = ? AND articles.archived = ? 
      AND (articles.body LIKE ? AND articles.body LIKE ?) 
      AND (articles.title LIKE ? OR articles.title LIKE ?)",
      true, false, "%intro%", "%demo%", "%article%", "%first%"]


As you can see we can get quite detailed in the queries this can create. Just use your imagination ;-) Also the test cases in the plugin source have many more examples to choose from.

Get it here: ez_where

Tags , , , ,  | 45 comments

A community effort book

Posted by ezmobius Tue, 20 Dec 2005 23:07:00 GMT


So i am busy writing my book over here. It’s a ton of work let me tell you. But it is going to be very rewarding.

The book is turning out to be a community effort of sorts. I have a few of my favorite and most respected rails developers writing parts of the book(topfunky & technoweenie) and the author of the great lighttpd webserver is going to personally cover the configuration of lighty in detail.

So if you don’t see me on the rails list or on #rubyonrails as much anymore you know where I went ;-)

Posted in , , , ,  | Tags , , , ,  | 5 comments

Older posts: 1 2