2016-05-10 7 views
0

Я хотел бы затенять ENV в методе шаблонов, чтобы я мог поднять ошибку, если запрошены ключи, которых нет в реальном ENV. Очевидно, я не хочу затенять константу в другом месте - только в рамках определенного метода (специфического привязки). Возможно ли это?Затенение константы верхнего уровня в привязке

Объяснитель: - Я знаю о существовании Hash#fetch, и я использую его все время и всюду. Тем не менее, я хочу использовать это в шаблоне ERB, создавая файл конфигурации. Этот файл конфигурации, вероятно, будет затронут больше людей, чем обычно, и не все знакомы с поведением Ruby, возвращающим nil для отсутствующего ключа Хэша. Я также работаю над системой, где в последнее время неудачи конфигурации (или неправильные конфигурации или недопонимание формата) вызвали заметные сбои в работе. Ошибки были ошибкой оператора. Поэтому я хотел бы установить соглашение только в пределах этого шаблона, что приведет к повышению. Более того, у меня есть драгоценный камень, strict_env, который делает это уже, но вы должны помнить, что используете STRICT_ENV вместо ENV, и каждый оператор «у вас есть» для этого конкретного рабочего процесса в этом конкретном случае вызывает красный флаг для меня, так как я хочу большей надежности. Я мог бы, конечно, выбрать более строгий язык шаблонов и использовать логику этого языка для повышения (например, Mustache), но так как команда уже знакома с ERB, а Rails поддерживает ERB-templated-YML как жизнеспособный конфигурационный подход (даже хотя вы можете не согласиться с этим) было бы неплохо, если бы я мог придерживаться этого рабочего процесса. Вот почему я хотел бы изменить поведение ENV[] локально.

+0

Некоторый код поможет. Не могли бы вы описать, как будет использоваться метод шаблонирования? – Stefan

+0

Нет, невозможно затенять константу. Это звучит, как [проблема XY] (http://xyproblem.info/). Вместо того, чтобы спрашивать, как затенять константу, дайте нам более подробную информацию о проблеме, которую вы пытаетесь решить, вместе с кодом, который вы написали до сих пор, и мы можем помочь вам найти лучшее решение. –

+0

То есть, предполагая, что мы используем одно и то же определение «тень» (чтобы определить переменную в локальной области с тем же именем, что и переменная из внешней области, такая, что она затеняет - «бросает тень» - исходная переменная). Опять-таки, некоторый код проделает долгий путь, помогая нам помочь вам. –

ответ

1

ERB#result принимает необязательный связывании:

require 'erb' 

class Foo 
    ENV = { 'RUBY_VERSION' => '1.2.3' } 
    def get_binding 
    binding 
    end 
end 

template = "Ruby version: <%= ENV['RUBY_VERSION'] %>" 

ERB.new(template).result 
#=> "Ruby version: 2.1.3" 

b = Foo.new.get_binding 

ERB.new(template).result b 
#=> "Ruby version: 1.2.3" 
+0

Ох! это аккуратно (и взломано, и я сказал аккуратно?) Будет играть с этим, спасибо! – Julik

0

Вы можете использовать ENV.fetch(key), чтобы поднять, когда ключа нет.

Кроме этого, вы можете создать класс и делегатом ENV, такие как:

class Configuration 
    def self.[](key) 
    ENV.fetch(key) 
    end 
end 

Но поднимая ошибку от #fetch вместо #[] более рубин, как так это то же самое поведение для Hash.

Наконец, вы могли бы обезьяна патч ENV, но это, как правило, не очень хорошая вещь, чтобы сделать:

def ENV.[](key) 
    fetch(key) 
end 

Насколько я знаю, вы не можете использовать refinements локализовать эту обезьяну патч, потому что ENV является объектом , а не класс, а его класс - Object.

+0

См. Объяснителя, который я только что добавил. Это может полностью работать, за исключением того, что люди будут продолжать использовать 'ENV ['smth']' вместо этого по привычке или будут вынуждены использовать абстракцию, где уже существует системная система по умолчанию. – Julik

+0

Я добавил путь к ENV, но он будет делать это глобально и возможно (возможно) в другом месте. – Kris