Почему Синатра копирует блок метода маршрута? - PullRequest
4 голосов
/ 29 ноября 2011

Это более сфокусированная версия моего предыдущего вопроса о том, как Синатра обрабатывал методы маршрутов.

Из моего понимания исходного кода Синатра берет блок метода в маршруте и передает новый метод, содержащий то же самое тело, т.е.:

get "some/url" do 
   return "Hello World" # this gets taken out
end

Таким образом, в этом примере тело метода, похоже, копируется в новый метод, который применяется к объекту Sinatra. Мне просто интересно, почему это происходит, я пытался зайти на их канал IRC, но там никого не было, и список рассылки не так занят.

Основная масса исходного кода, о котором я говорю в их среде, находится внутри base.rb в строке 1180:

  def generate_method(method_name, &block)
    define_method(method_name, &block)
    method = instance_method method_name
    remove_method method_name
    method
  end

Так есть ли какая-то конкретная причина, почему они делают это, а не просто ссылаются на сам метод?

Причина, по которой я задаю этот вопрос, заключается в том, что метод, который Синатра в настоящее время обрабатывает, делает невозможным использование метода, обладающего знаниями вне себя, и нарушает инкапсуляцию классов, просто принимая один метод без контекста.

Ответы [ 3 ]

4 голосов
/ 02 декабря 2011

Как и в комментариях выше, это генерирует метод.Правильный метод.Если Синатра не удалит метод снова в generate_method, вы можете вызвать его, выполнив что-то вроде send("GET some/url").Вопрос в том, почему Синатра снова удаляет этот метод?Проще говоря, может быть более одного обработчика на маршрут:

get 'some/route' do
  pass if request.referrer == '/foo'
  "didn't come from /foo"
end

get 'some/route' do
  "did come from /foo"
end

Оба метода имеют одинаковые имена.

Что касается ваших комментариев о подклассах и методах, это должно сработать:

class MyApp < Sinatra::Base
  def content
    return "did come from /foo" if request.referrer == '/foo'
    "didn't come from /foo"
  end

  get('some/route') { content }
end

Или при выполнении классического приложения:

helper do
  def content
    return "did come from /foo" if request.referrer == '/foo'
    "didn't come from /foo"
  end
end

get('some/route') { content }
3 голосов
/ 29 ноября 2011

Я предполагаю, что они хотят иметь полноценный метод (с доступом к другим методам экземпляра и класса) для каждого маршрута, но не хотят загрязнять пространство имен. Имя метода генерируется как "#{verb} #{path}", поэтому если, например, у вас есть несколько маршрутов с разными условиями для одних и тех же путей, столкновения неизбежны, если вы не удалите метод сразу после определения и сохранения его где-то еще. И это именно то, что они делают. Метод не связан, но это не проблема, так как позже они могут привязать его к любому экземпляру класса.

Обратите внимание, это только предположение. Я не очень знаком с Sinatra, так что за этой реализацией может быть совершенно другая идея.

0 голосов
/ 03 января 2013

Я думаю, он просто имитирует instance_exec для поддержки Ruby старше 1.8.7

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...