2013-08-09 2 views
2

Я ищу способы DRY моего приложения Sinatra и столкнулся с некоторыми проблемами, связанными с определением области обзора - в частности, помощники и функции Sinatra недоступны внутри моих обработчиков. Может кто-нибудь, пожалуйста, скажите мне, есть ли способ исправить этот код и что еще более важно, что происходит?Sinatra, DRY и scoping

спасибо.

require 'sinatra' 
require 'pp' 

helpers do 
    def h(txt) 
    "<h1>#{txt}</h1>" 
    end 
end 

before do 
    puts request.path 
end 


def r(url, get_handler, post_handler = nil) 
    get(url){ get_handler.call } if get_handler 
    post(url){ post_handler.call } if post_handler 
end 


routes_composite_hash = { 
    '/' => lambda{ h('index page'); pp params }, #can't access h nor params!!! 
    '/login' => [lambda{'login page'}, lambda{'login processing'}], 
    '/postonly' => [nil, lambda{'postonly processing'}], 
} 

routes_composite_hash.each_pair do |k,v| 
    r(k, *v) 
end 

ответ

2

Интересно!

ли это:

def r(url, get_handler, post_handler = nil) 
    get(url, &get_handler) if get_handler 
    post(url, &post_handler) if post_handler 
end 


routes_composite_hash = { 
    '/' => lambda{ h('index page'); pp params }, 
    '/login' => [lambda{'login page'}, lambda{'login processing'}], 
    '/postonly' => [nil, lambda{'postonly processing'}], 
} 

routes_composite_hash.each_pair do |k,v| 
    r(k, *v) 
end 

Как Kashyap объясняет, вы позвонив и опубликовать обработчик внутри main контекста. Это просто преобразует отправленную лямбду в блок и передает ее желаемому методу.

+0

Ах очень хорошо, я не знал, что вы можете передать блок напрямую, чтобы получить/отправить! Огромное спасибо! – rebnoob

1

Методы, определяющие внутри helpers do .. end блоков доступны только внутри маршрутов и фильтров и взглядов контекстов и, таким образом, так как вы не используете их в любой из них, он не будет работать. Lambdas сохраняет контекст выполнения, что означает, что в хеш-файле {'/' => lambda { h }..} контекст равен main, но внутри метода get контекстные изменения и помощники доступны только в этом контексте.

Чтобы достичь того, что вы хотите сделать (хотя я бы предложил вам избежать этого), вы можете просто определить помощников как lambdas внутри вашего файла приложения. В вашем случае, это было бы:

def h(txt) 
    "<h1>#{txt}</h1>" 
end 

# And then the rest of the methods and the routes hash 

Таким образом, метод h в контексте main объекта и, таким образом, будет виден всем.

+0

Должен быть способ оценить блок в определенном контексте, но я не смог это сделать. – Kashyap

+0

Спасибо за объяснение, действительно помогает – rebnoob