Pull to refresh

Как реализовать паттерн HMVC в Rails

Reading time2 min
Views1.9K
Original author: r_wilco



Rails engins? Нет!


Это прекрасный способ создавать «встраиваемые» приложения. Но если Вы хотите сделать запрос в другой engine, это заблокирует еще один инстанс Вашего сервера. Поэтому, если у Вас будет высокоуровневая HMVC структура, то Вы должны будете иметь много запущенных инстансов приложения, чтобы обеспечить работу приложения.

Решение: async-rails


Я считаю, что хорошее решение этой проблемы это совместное использование Rails engines и async-rails

Предположим, что у нас есть engine, который реализует некий FooController с экшеном #bar:
module MyEngine
  class FooController < ::ApplicationController
    def bar
      render the: text => "Your text is #{params[:text]}"
    end
  end
end


Добавим в 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'


А эту строку в config.ru:
...
use Rack::FiberPool # <-- ВОТ ЭТУ
run HmvcTest::Application


А вот это в config/application.rb:
...
    config.threadsafe! # <--  ВОТ ЭТО
  end
end


Теперь мы можем делать запросы из любой части нашего приложения в 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


Теперь запустим сервер:
this start


и откроем http://localhost:3000/home/index?a=HMVC в броузере:


В rails логе мы получим:
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)


Мы сделали один запрос внутри другого. Похоже, все ok!

Проблемы


Этот подход имеет несколько недостатков:
  • нет способа изолировать engine от запросов из внешеного мира (каждый может сделать запрос к FooController напрямую);
  • все логи пишутся в один файл


Ссылки


  1. Scaling Web Applications with HMVC article by Sam de FreThe
  2. https://github.com/igrigorik/async-rails
Tags:
Hubs:
Total votes 14: ↑9 and ↓5+4
Comments28

Articles