#ruby #string #templates #eval #erb
#ruby #строка #шаблоны #вычисление #erb
Вопрос:
В чем различия между нотацией:
"
some text
#{some_ruby_code}
some text
#{some_more_ruby_code}
some_other_text
"
и
ERB.new("
some text
<%=some_ruby_code%>
some text
<%=some_more_ruby_code%>
some_other_text
").result
У меня просто сложилось общее впечатление, что нотация erb может быть более мощной, но я не настолько ясен. Можете ли вы сравнить их с разных точек зрения и сказать, какие из них следует использовать в каких случаях? Какие вещи могут быть выполнены в одной нотации, а не в другой?
Дополнение 1
Большинство ответов на данный момент, похоже, утверждают, что erb неэффективен и не должен использоваться, когда "#{ }"
может быть использован. Теперь давайте зададим другой вопрос. Почему "#{ }"
нотация не может заменить erb? Разве это не было бы намного быстрее и лучше?
Дополнение 2
Большинство ответов ниже, похоже, предполагают, что одно событие "#{ }"
не распространяется на несколько строк, так что фрагмент кода, подобный циклу, занимающему несколько строк, не может быть встроен внутрь. Но почему бы и нет? Если вы это сделаете, я не вижу никакой разницы от выполнения этого с <% >
, за исключением того, что в последнем случае вы вставляете <% >
в каждую строку.
Комментарии:
1. Я не разработчик ruby, но я бы выбрал наименее мощный и наиболее читаемый синтаксис в любое время. Это предотвращает добавление логики в представления, которой там не место, и облегчает чтение представлений.
2. @jgauffin Я согласен. И вы, вероятно, имеете в виду, что
"#{ }"
следует отдавать предпочтение erb, когда это возможно. Тогда, когда следует использовать erb? Почему это может быть заменено на"#{ }"
?3. Я не большой поклонник ERB и был бы счастлив, если бы он вообще не использовался. OTOH, это стандарт, и каждому поколению нужен свой собственный ужасный стандарт, который все используют (Fortran, SQL, ERB, RPG, JCL, …).
4. @muistoosh SQL — это реальный язык для доступа к базе данных, и его невозможно избежать, в отличие от ERB. Настоящий язык — HTML; ERB — это просто промежуточный язык, поэтому у него меньше основы. Пока у вас есть другие способы генерировать HTML, вам может сойти с рук ERB.
Ответ №1:
Вы правы в том, что ваша ERB
версия должна выдавать тот же результат, что и обычная версия (я думаю), но ее назначение совершенно иное.
ERB
на самом деле это просто для создания шаблонов: если вам нужно сгенерировать текст (например, HTML-страницу или документ), какой-нибудь движок для создания шаблонов, подобный ERB
, будет подходящим инструментом. Тем не менее, он не предназначен для простой интерполяции строк: хотя он, безусловно, способен это делать, это довольно периферийный способ сделать это. Действительно, вы фактически создаете ERB
объект из строки, а затем оцениваете его обратно в строку.
Вы можете получить представление о том, насколько это неэффективно, проведя быстрый тест:
$ irb -rbenchmark -rerb
ruby-1.9.2-p136 :023 > Benchmark.bm do |bm|
ruby-1.9.2-p136 :024 > bm.report 'interpolation' do
ruby-1.9.2-p136 :025 > a = 'hello there'
ruby-1.9.2-p136 :026?> 5000.times { "well #{a}" }
ruby-1.9.2-p136 :027?> end
ruby-1.9.2-p136 :028?> bm.report 'erb' do
ruby-1.9.2-p136 :029 > a = 'hello there'
ruby-1.9.2-p136 :030?> 5000.times { ERB.new("well <%= a %>").result(binding) }
ruby-1.9.2-p136 :031?> end
ruby-1.9.2-p136 :032?> end
user system total real
interpolation 0.000000 0.000000 0.000000 ( 0.001495)
erb 0.340000 0.000000 0.340000 ( 0.352098)
=> true
Стандартным способом интерполяции кода Ruby в строки является использование #{}
внутри строкового литерала. Это встроено на уровне языка (в отличие от уровня библиотеки).
Комментарии:
1. Вы убедительно показываете, насколько медленным является erb. Тогда почему нельзя создать шаблон с помощью
"#{ }"
?2. @sawa: Я полагаю, что это было бы возможно, но для этого потребовался бы запуск
gsub
илиeval
для загруженной строки. ERB допускает простую интерполяцию наряду с циклированием, условными обозначениями и так далее.3. @Hans Почему нельзя встроить циклирование, условные обозначения и другие вещи
"#{ }"
? Я не понимаю, почему"#{ }"
требуетсяgsub
, в то время как erb этого не делает.4. @Jonathan, нет проблем! @sawa, если только все эти строки, которые вы пишете, не являются статическими в вашем коде, вам нужно будет использовать некоторую комбинацию
gsub
иeval
для замены вхождений#{...}
в пределах динамически генерируемой строки. ИМХО, лучше полагаться на библиотеки шаблонов (ERB и friends) для фактического создания шаблонов и использовать встроенную интерполяцию строк (#{...}
) внутри вашего статического кода.5. Действительно!
#{}
работает в строковых литералах. Когда вы загружаете строку динамически, она будет отображаться в строке как »#{}
«; поэтому вам пришлось бы переопределить функциональность#{}
, если вы собирались использовать ее вне строкового литерала. И тогда вам придется переопределить частьERB
. Понимаете, к чему я клоню?
Ответ №2:
Преимущества ERB:
- Все уже знают и «любят» этот PHP-подобный стиль
- Вам не нужно беспокоиться о балансировке или экранировании
'
или"
- Обычно вам не нужно программировать базовый механизм Ruby, т. Е. вам не нужно определять метод, возможно, расположенный в классе, возможно, дополненный модулем и т.д…
В общей картине, я полагаю, общая идея заключается в том, чтобы отделить части программы, которые должны быть выполнены разработчиком программного обеспечения, от той части, которую может выполнить интерфейсный веб-разработчик. Например, разработчик программного обеспечения может просто указать, что @account_number
доступно, и на него могут ссылаться HTMLеры без квалификации Ruby.
В реальной жизни, похоже, существует множество проектов, выполняемых одним человеком, но, по крайней мере, когда-то нормой было привлекать команду к решению типичной проблемы. Даже сегодня посмотрите на все вопросы Rails здесь, на SO, от разработчиков, которые, очевидно, почти не знают Ruby. И ERB предшествует Rails, поэтому, если вы вернетесь к истокам механизма, было время, когда вам действительно всегда был нужен настоящий отдел программного обеспечения, потому что каждый проект включал в себя создание фреймворка, поэтому вы, вероятно, не хотели требовать квалификации Ruby software от каждого последнего члена команды.
Теперь я понимаю, что вы имеете в виду. Если вы уже знаете Ruby, намного сложнее оправдать уродство erb.
Комментарии:
1. Что касается ваших первых двух пунктов, я думаю, это просто тонкая разница в том, как вы выходите и переходите в режим кода. Что касается вашего третьего пункта, я не вижу, как это не относится к нотации «# { }».
2. Я бы отметил, что не всем нравится синтаксис PHP. Вот почему существуют такие проекты, как haml.
3. @egarcia: верно, вот почему я написал это с кавычками для запугивания , которые означают, что я не собираюсь ссылаться на буквальное значение фразы. Разве я не говорил , что это уродливо?
4. @sawa: что касается третьего пункта, то я пытался сказать следующее: обычно синтаксис ERB находится в файле шаблона, управляемом Rails или Puppet, или какой-либо другой платформой. Так что это всего лишь шаблон. Здесь не указано
ERB.new( ... )
, потому что фреймворк считывает файл шаблона. Но в известных мне фреймворках нет соответствующего механизма для файлов с голыми объектами RubyString
в них. Конечно, такую вещь можно было бы разработать тривиально, но в настоящее время это не функция, и поэтому ответ на ваш вопрос таков: фреймворки поддерживают ERB, а не голые объекты RubyString
.
Ответ №3:
Одним из недостатков попыток использовать ERB для общей интерполяции строк является то, что ERB действительно нацелен на генерацию HTML. Результатом будет множество проблем с кодированием, когда вы забудете все выполнить в необработанном виде и запутаетесь в том, почему ваши символы амперсандов, больше, чем, меньше, чем и т.д. искажаются.
Я думаю, что для ERB также будет больше вычислительных затрат, но это может не иметь значения.
Кроме того, если вы поместите встроенный ERB внутри Ruby, в конечном итоге Ruby inside ERB окажется внутри Ruby (и, вполне возможно, больше уровней, поскольку вы вызываете методы из ERB), и это будет немного запутанным беспорядком. Подумайте о беднягах, которым придется поддерживать ваш код, возможно, это даже вы сами.
ОБНОВЛЕНИЕ: Вы могли бы использовать #{}
для простых HTML-шаблонов (см. Mustache для чего-то подобного), но было бы сложно и довольно некрасиво создавать повторяющийся раздел; повторяющиеся разделы довольно распространены в HTML-шаблонах, так что это должно быть легко и естественно для системы шаблонов HTML. С помощью ERB вы можете просто:
<% a.each do |e| %>
<!-- ... -->
<% end %>
но это было бы ошибкой при #{}
интерполяции. Вы также в конечном итоге будете делать #{html(blahblah)}
все время, и большинство людей забудут.
Кроме того, «#» имеет особое значение в URL-адресах и другое специальное значение в CSS (где фигурные скобки также имеют особое значение); фрагментированные URL-адреса и фрагменты CSS довольно распространены в шаблонах HTML, поэтому вы постоянно беспокоитесь о том, чтобы что-то перепутать. Эта конкретная неприятность, вероятно, была бы проблемой только при использовании #{}
для создания CSS-селектора или фрагмента в URL-адресе, но этого достаточно, чтобы сделать его громоздким.
Комментарии:
1. Что касается вашего первого пункта, я думаю, это просто разница в том, что нужно экранировать. Я согласен с вами, что erb все усложнит. Тогда почему
"#{ }"
нотацию нельзя использовать там, где используется erb?2. Следуя вашим аргументам, единственное существенное различие, которое я вижу, — это escape-символ. Таким образом, единственной причиной наличия erb было бы то, что в ruby отсутствует альтернативная нотация для
"#{ }"
, которая не конфликтует с html, css или xml. Я не понимал, почему было бы беспорядочно использовать"#{ }"
интерполяцию помимо проблемы с экранированием.3. @mu Я думаю, что я кое-что понял из этих ответов. Ваши ответы и ответы других являются конструктивными.