пятница, 3 февраля 2012 г.

How to implement HVMC in Rails




The problem is how to implement this pattern in Rails.

Rails engines? No!
It is a great way to make "pluggable" applications. But if you want to make request to some engine this request should block another instance of your server. So, if you have high-level HMVC structure you must have a lot of  rails-instances to serve your application.

Solution: async-rails
I think, that nice solution of this problem is a composite of Rails engines and async-rails. So let's rock!

Let's assume that we have an engine that implements some FooController with a #bar action:
module MyEngine
  class FooController < ::ApplicationController
    def bar
      render the: text => "Your text is #{params[:text]}"
    end
  end

end

Add to your Gemfile:

gem 'thin' # yes, we're going to use thin!
gem 'rack-fiber_pool', :require => 'rack/fiber_pool'


# async http requires
gem 'em-synchrony', :git => 'git://github.com/igrigorik/em-synchrony.git',  :require => 'em-synchrony/em-http'
gem 'em-http-request',:git => 'git://github.com/igrigorik/em-http-request.git', :require => 'em-http'
gem 'addressable', :require => 'addressable/uri'




Add this line to config.ru: 
...
use Rack::FiberPool # <-- THIS ONE
run HmvcTest::Application

Add this to your config/application.rb:

...
    config.threadsafe! # <-- THIS ONE
  end
end


Now we can make a request from any part of our application to the FooController:


class HomeController < ApplicationController
  def index
    http = EM::HttpRequest.new("http://localhost:3000/foo/bar?text=#{params[:a]}").get


    render :text => http.response
  end
end


Now you can start thin:
$ thin -D start

and open http://localhost:3000/home/index?a=HMVC in your browser:

In Rails log we have:
Started GET "/home/index?a=HMVC" for 127.0.0.1 at 2012-02-03 15:27:02 +0400
Processing by HomeController#index as HTML
  Parameters: {"a"=>"HMVC"}


Started GET "/foo/bar?text=HMVC" for 127.0.0.1 at 2012-02-03 15:27:02 +0400
Processing by FooController#index as HTML
  Parameters: {"text"=>"HMVC"}
  Rendered text template (0.0ms)
Completed 200 OK in 1ms (Views: 0.6ms | ActiveRecord: 0.0ms)
  Rendered text template (0.0ms)
Completed 200 OK in 6ms (Views: 0.4ms | ActiveRecord: 0.0ms)

We have one request inside the other. So we done!

Problems
This approach has some disadvantages:
  • there is no way to isolate engine from outside world (everybody can make request directly to FooController)
  • all logs are written to the same file
Links


Комментарии

технология комментирования HyperComments


2008–2014 © Сергей Удалов Реклама Система Orphus