В предыдущей статье мы создали «драгоценный камень» с нуля, который включает плагин jQuery и добавляет его в приложение Rails. В этом посте давайте рассмотрим некоторые продвинутые концепции, чтобы сделать наш камень еще лучше.
Мы будем использовать то же приложение gem и Rails, что и в предыдущем посте.
Пользовательский Помощник
До сих пор мы успешно применяли эффект масштабирования к изображениям, просто добавляя CSS-класс image_zoomer
. Но вы не думаете, что наш драгоценный камень заслуживает специального помощника? Я имею в виду, не лучше ли использовать наш собственный вспомогательный тег и освободить пользователя от необходимости добавлять CSS-класс image_zoomer
?
Давайте создадим собственный помощник с именем zoom_image_tag
. К изображениям, добавленным с помощью zoom_image_tag
будет применен эффект масштабирования по умолчанию. Создайте файл с именем zoom_image_helper.rb в каталоге lib / image_zoomer в геме и вставьте следующий код:
module ImageZoomer def zoom_image_tag(*args, &block) options = insert_zoom_class(args.extract_options!) args << options image_tag(*args, &block) end def insert_zoom_class(options) class_name = "image_zoomer" if options.key?(:class) options[:class] += " #{class_name}" elsif options.key?('class') options['class'] += " #{class_name}" else options[:class] = class_name end options end end
Мы определили два метода в модуле ImageZoomer
. Метод zoom_image_tag
получает несколько аргументов и блок, как и помощник image_tag
.
options = insert_zoom_class(args.extract_options!)
вызывает extract_options!
метод, предоставляемый ActiveSupport
. Он используется для извлечения параметров из набора аргументов. Он удаляет и возвращает последний элемент в массиве, если это хеш, в противном случае он возвращает пустой хеш. insert_zoom_class
хеш передается в insert_zoom_class
.
insert_zoom_class
— это простой метод, используемый для вставки class
в предоставленный хеш. Ключ может быть символом, строкой или не предоставляться вообще. Здесь image_zoomer
class
image_zoomer
возвращается как часть хэша.
args appends the
хэш options
к args
. Так как extract_options!
удаляет параметры из args
, мы должны добавить их обратно.
image_tag(*args, &block)
является стандартным помощником Rails image_tag
с нашими измененными аргументами. zoom_image_tag
здесь: zoom_image_tag
— это просто обертка для image_tag
. У пользователей нашего драгоценного камня теперь есть удобный способ облегчить их жизнь.
Перейдите в тестовое приложение Rails и откройте app / views / site / index.html.erb в вашем приложении Rails и замените image_tag
на:
<%= zoom_image_tag("test.jpg"); %>
Запустите веб-сервер и откройте в браузере http: // localhost: 3000 / site / index . Вы увидите ошибку, в которой указано что-то вроде undefined method 'zoom_image_tag'
. Что происходит?? Мы не говорили Rails, что zoom_image_tag
— это вспомогательный метод. Давайте сделаем это сейчас.
Мы знаем, что помощник image_tag
определен в ActionView::Helpers::AssetTagHelper
. Мы можем просто снова открыть эти модули и добавить модуль ImageZoomer
. Откройте lib / image_zoomer.rb (в геме) и добавьте:
require "image_zoomer/zoom_image_helper" module ActionView module Helpers module AssetTagHelper include ImageZoomer end end end
Теперь zoom_image_tag
станет частью методов ActionView::Helpers::AssetTagHelper
, присоединившись к лиге других помощников, таких как image_tag
, javascript_include_tag
и т. Д.
Перезагрузите веб-сервер и обновите страницу. Эффект масштабирования изображения применяется с помощью нашего нового помощника. Здорово.
Важный рефакторинг
Включение ImageZoomer
в существующий модуль является разновидностью Monkey Patching и считается вредным. К счастью, Rails предоставляет элегантный способ добавления пользовательских помощников, называемых Railties, которые не используют Monkey Patching. Railties предоставляют несколько хуков для участия в процессе инициализации. Узнайте больше о Railtie
здесь .
Сначала удалите недавно вставленный код из lib / image_zoomer.rb, чтобы он состоял только из трех операторов require
. Создайте файл railtie.rb в каталоге lib / image_zoomer / с помощью:
class Railtie < Rails::Railtie initializer "image_zoomer.initialize_zoom_image_helper" do |app| ActiveSupport.on_load(:action_view) do include ImageZoomer end end end
Вот наш класс Railtie
который Railtie
от Rails::Railtie
в соответствии с документацией Rails. Вызов метода initializer
принимает имя и блок. Блок делает нашу магию, вызывая ActiveSupport.on_load(:action_view)
и передавая другой блок для включения модуля ImageZoomer
. Наш модуль ImageZoomer
будет включен только ActionView
полной загрузки ActionView
. Это стандартный способ добавления помощников начиная с Rails 3. Подробнее об этом здесь .
Требуйте railtie.rb в lib / image_zoomer.rb со следующим кодом:
require "image_zoomer/railtie"
Сохраните изменения, перезапустите веб-сервер и обратите внимание, что эффект масштабирования все еще работает. Теперь zoom_image_tag
вставляется встроенными хуками Rails, и мы исключили Monkey Patching.
Наша окончательная версия lib / image_zoomer.rb выглядит так:
require "image_zoomer/version" require "image_zoomer/engine" require "image_zoomer/zoom_image_helper" require "image_zoomer/railtie"
Переопределение конфигураций по умолчанию
Наш драгоценный камень работает нормально, и мы можем назвать его «готовым», но действительно ли он расширяемый? Под «расширяемым» я имею в виду, может ли разработчик изменить стандартную конфигурацию плагина jQuery? По умолчанию height
и width
зум-объектива составляет 90px
а zoom-level
— 1.5
. Если разработчик не может обновить эти настройки, наша жемчужина не расширяема. Другими словами, мы еще не закончили.
Давайте добавим некоторую расширяемость, чтобы разработчики могли легко переопределить настройки по умолчанию.
Класс конфигурации
Создайте класс для хранения нашей конфигурации в файле с именем lib / image_zoomer / configuration.rb в вашем геме и добавьте:
module ImageZoomer class Configuration attr_accessor :width, :height, :zoom_level def initialize @width = 90 @height = 90 @zoom_level = 1.5 end end end
Мы просто создали класс в нашем модуле ImageZoomer
. Класс Configuration
имеет три свойства: width
, height
и zoom_level
. Экземпляры этого класса получат значения по умолчанию, которые соответствуют определенным плагином jQuery.
Требуется файл configuration.rb в lib / image_zoomer.rb :
require "image_zoomer/configuration"
Лучшее место для создания экземпляра этого класса — в lib / image_zoomer / railtie.rb . Добавьте следующий код в наш класс Railtie
:
initializer "image_zoomer.configuration" do |app| app.config.image_zoomer = ImageZoomer::Configuration.new end
Мы снова вызываем метод initializer
и передаем ему имя и блок. app
здесь представляет Rails.application
а app.config
является экземпляром Rails::Application::Configuration
используемым для хранения всей конфигурации приложения. Мы создали экземпляр ImageZoomer::Configuration
и присвоили его app.config.image_zoomer
.
Теперь доступ к Rails.application.config.image_zoomer
представит экземпляр ImageZoomer::Configuration
. Перезагрузите веб-сервер, обновите браузер и убедитесь, что мы ничего не сломали.
Чтобы немедленно поиграть с экземпляром ImageZoomer::Configuration
, запустите консоль ( rails console
) и введите Rails.application.config.image_zoomer
. Если все настроено правильно, вы увидите наш ImageZoomer::Configuration
в действии.
Предоставление настроек плагину
У драгоценного камня теперь есть класс конфигурации, нам нужно только использовать его. Создайте новый файл с именем image_zoomer_options.js.erb в app / assets / javascripts под гемом с помощью:
var __ImageZoomer = { options: { width: "<%= Rails.application.config.image_zoomer.width %>", height: "<%= Rails.application.config.image_zoomer.height %>", zoom_level: "<%= Rails.application.config.image_zoomer.zoom_level %>" } }
Приведенный выше код довольно прост. __ImageZoomer
переменную JavaScript ( __ImageZoomer
) и __ImageZoomer
ей объект со свойством с именем options
. У объекта options
есть три свойства, которые соответствуют свойству объекта Rails.application.config.image_zoomer
. Это шаблон erb
потому что мы хотим выполнить некоторый код Ruby, а Sprockets автоматически обрабатывает выполнение динамического кода в файлах ресурсов. Таким образом, image_zoomer_options.js.erb
укажет результат в /assets/image_zoomer_options.js в ответе HTML и будет выглядеть так:
var __ImageZoomer = { options: { width: "90", height: "90", zoom_level: "1.5" } }
Как видите, наш динамический код выполняется, а width
, height
и zoom_level
имеют значения по умолчанию, которые мы определили в конструкторе ImageZoomer::Configuration
.
С нашим новым объектом JavaScript, содержащим значения конфигурации, пришло время изменить код инициализации плагина jQuery для его использования. Откройте app / assets / javascripts / image_zoomer_initializer.js под вашим гемом и замените существующий код на:
$(function() { if (typeof __ImageZoomer == "undefined") { __ImageZoomer = {options: {}}; } $(".image_zoomer").each(function() { $(this).image_zoomer(__ImageZoomer.options); }); });
Сначала проверьте, существует ли переменная __ImageZoomer
и создайте ее, если необходимо. В соответствии с использованием плагина jQuery мы можем передать объект в метод image_zoomer
и свойства, определенные в этом объекте, будут применены. При __ImageZoomer.options
наши настройки применяются для изменения режима масштабирования изображения.
Перезапустите свой веб-сервер, обновите браузер, и вы должны увидеть то же изображение. __ImageZoomer
указывает на значения по умолчанию, поэтому на данный момент нет изменений в масштабировании. Но мы сделали важный шаг к тому, чтобы дать пользователям возможность изменить настройки по умолчанию.
Изменение значений по умолчанию в Rails
Rails использует инициализаторы для изменения конфигурации для гемов и основных настроек Rails. Мы тоже так сделаем. Во-первых, в ImageZoomer::Configuration
должен быть элегантный способ обновления свойств. Откройте lib / image_zoomer / configuration.rb и добавьте в класс следующий метод:
# Override default options with the provided ones in block def set_options(&block) block.yield(self) end
Мы создали метод set_options
который принимает блок, который set_options
self
(текущий экземпляр конфигурации). Вызов этого метода с соответствующим блоком обновит значения по умолчанию Image_Zoomer::Configuration
из нашего инициализатора Rails.application.config.image_zoomer
.
В приложении Rails создайте config / initializer / image_zoomer.rb с помощью:
Rails.application.config.image_zoomer.set_options do |options| options.width = 50 options.height = 50 end
Когда этот код выполняется, width
и height
изменяются на 50
, а image_zoomer
по-прежнему равен 1.5
потому что мы его не меняли. Разработчики могут легко изменить этот блок в соответствии со своими потребностями. Поскольку мы уже настроили наш код jQuery таким образом, чтобы он выбирал последние значения из нашего Rails.application.config.image_zoomer
мы готовы к работе.
Перезапустите веб-сервер, обновите браузер и обратите внимание на width
и height
отличные от предыдущих.
Исправление предостережения
Подождите, ширина и высота не изменились. Что происходит? Это связано с одной оговоркой.
Sprockets кэширует ресурсы, чтобы им не приходилось обрабатывать их снова и снова. Когда любой ресурс обслуживается в первый раз, он кэшируется, и этот кеш будет обслуживаться при последующих запросах. Этот кеш не будет обновляться, даже когда мы перезапускаем веб-сервер. Один из способов обновить кэш для любого ресурса — это изменить его исходный код, но это может привести к бесполезным изменениям и глупым коммитам, полным пустых мест / строк. Давайте посмотрим на лучший способ. Откройте lib / image_zoomer / railtie.rb и измените блок image_zoomer.configuration
следующим образом:
initializer "image_zoomer.configuration" do |app| app.config.image_zoomer = ImageZoomer::Configuration.new # Clear the cache FileUtils.rm_rf("#{Rails.application.root}/tmp/cache/assets") if Rails.env.development? end
Звездочки хранят кэши по указанному пути в нашем приложении Rails. Мы удаляем этот каталог, когда выполняется код в нашем lib / image_zoomer / railtie.rb (когда сервер запускается и гем загружается). Мы используем встроенные в Ruby методы для удаления этой папки в среде разработки.
Перезапустите веб-сервер, и вы, наконец, увидите зум-объектив с разными размерами. Идите вперед и измените настройки в config / initializers / image_zoomer.rb на свое усмотрение .
Публикация драгоценного камня
Наш драгоценный камень готов. Публиковать гем довольно просто, благодаря основной команде Rubygems. Bundler уже предоставил некоторые задачи, которые полезны при упаковке и распространении драгоценных камней. Во-первых, вы должны иметь учетную запись Rubygem. Зайдите на http://rubygems.org и зарегистрируйтесь.
После создания учетной записи обновите соответствующую информацию в файле image_zoomer.gemspec . Вы, вероятно, захотите перенести этот самоцвет в Github.
Перейдите в корневой каталог вашего драгоценного камня и введите следующую команду:
rake release
Эта команда скомпилирует все необходимые файлы в пакет .gem
, передаст последний код вместе (с версией gem) в качестве тега в GitHub и загрузит гем в Rubygems. Во время публикации вам будет предложено ввести учетные данные Rubygems, предоставьте их и все готово. Как только камень будет успешно опубликован, вы увидите это в своей панели на Rubygems.
Если по какой-то причине не rake release
, вы также можете собрать гем, используя rake build
. Если это работает, вручную image_name-version.gem
сгенерированный image_name-version.gem
в Rubygems с помощью gem push path/to/image_name-version.gem
.
Одна вещь, оставленная
Теперь осталось только одно — поделиться своей жемчужиной с коллегами, друзьями и другими рубиистами. Не забудьте написать письмо Питеру Куперу, чтобы опубликовать его в RubyWeekly, одном из самых читаемых информационных бюллетеней Ruby.
Вывод
Создание чего-то и содействие открытому исходному коду — потрясающий опыт, и каждый разработчик должен это делать. Я надеюсь, что вы узнали много в этих двух статьях. Идите вперед и сделайте драгоценный камень для вашего любимого плагина jQuery.