Записи с меткой ‘rails’
Тестирование модулей с помощью RSpec
К примеру, у нас есть такой модуль, который мы добавляем в классы Airport, City:
extend ActiveSupport::Concern
module InstanceMethods
def name locale=:en
locale = :en if !name_ru || name_ru.empty?
send(name_method(locale))
end
def localized_name
name(I18n.locale || :en)
end
private
def name_method locale=:en
"name_#{locale}".to_sym
end
end
included do
field :name_en, :type => String
field :name_ru, :type => String
validates_presence_of :name_en
end
end
include Mongoid::Document
include Nameable
end
include Mongoid::Document
include Nameable
end
Чтобы протестировать модуль, для него нужно создать shared_examples_for блок:
it{should have_fields(:name_en).of_type(String)}
it{should have_fields(:name_ru).of_type(String)}
it{should validate_presence_of(:name_en)}
describe '#name' do
specify{nameable.name(:en).should == 'Name'}
specify{nameable.name(:ru).should == 'Имя'}
context 'if russian name is null' do
before do
nameable.name_ru = nil
end
specify{nameable.name(:en).should == 'Name'}
specify{nameable.name(:ru).should == 'Name'}
end
end
# И так далее...
end
В блоке используется одна переменная nameable, которая будет определяться в спеке того класса, к которому мы подключим модуль. То есть в spec/models/airport_spec.rb пишем примерно так:
require 'models/nameable_spec'
describe Airport do
it{should be_mongoid_document}
before do
Airport.delete_all
end
context do
let(:nameable){Factory.create(:airport,
:name_en => 'Name',
:name_ru => 'Имя'
)}
it_behaves_like :Nameable
end
Вобщем то, переменных может быть сколько угодно, это зависит от тестируемого модуля. Теперь добавляем примерно тоже самое в spec/models/city_spec.rb:
require 'models/nameable_spec'
describe City do
it{should be_mongoid_document}
before do
City.delete_all
end
context do
let(:nameable){Factory.create(:city,
:name_en => 'Name',
:name_ru => 'Имя'
)}
it_behaves_like :Nameable
end
Запускаем тест:
Работает. Запускаем несколько тестов:
Тесты вызывают ошибку:
from /Users/undr/.rvm/gems/ruby-1.9.2-p180/gems/rspec-core-2.6.4/lib/rspec/core/shared_example_group.rb:8:in `shared_context'
from /Users/undr/projects/ruby/*******/spec/models/nameable_spec.rb:1:in `<top (required)>'
from /Users/undr/.rvm/gems/ruby-1.9.2-p180/gems/activesupport-3.1.0/lib/active_support/dependencies.rb:234:in `load'
from /Users/undr/.rvm/gems/ruby-1.9.2-p180/gems/activesupport-3.1.0/lib/active_support/dependencies.rb:234:in `block in load'
...
Чтобы избежать этого надо предотвратить повторное определение блока shared_examples_for. Просто этот перед определением блока делайте проверку на его наличие:
shared_examples_for :Nameable do
...
end
end
Таким образом у меня получилось удобно, без лишнего кода, тестировать модули подмешанные к классам.
Доклад по Grape
Доклад по Grape
http://confreaks.net/videos/475-rubyconf2010-the-grapes-of-rapid
Тестовое приложение
MongoId документы и метод to_a
Сегодня натолкнулся на странный баг в программе. Использовал Mongoid для работы с MongoDb. Моделька была примерно такая:
field :coordinates, :type => Array
field :index, :type => Integer
index [[ :coordinates, Mongo::GEO2D ]]
referenced_in :parent, :class_name => 'Content::City', :inverse_of => :children, :index => true, :validate => false
def city
parent
end
def to_a
[
code,
name,
coordinates.try(:join, ':'),
city.try(:name),
city.try(:index).try(:to_i),
index.to_i
]
end
end
В классе Content::Place добавлялись некоторые общие поля и модуль Mongoid::Tree.
При попытке создать аэропорт привязанный к городу выпадала ошибка:
from /Users/undr/.rvm/gems/ruby-1.9.2-p180/gems/bson-1.3.1/lib/bson/bson_c.rb:24:in `serialize'
from /Users/undr/.rvm/gems/ruby-1.9.2-p180/gems/bson-1.3.1/lib/bson/bson_c.rb:24:in `serialize'
from /Users/undr/.rvm/gems/ruby-1.9.2-p180/gems/mongo-1.3.1/lib/mongo/cursor.rb:425:in `construct_query_message'
Кэширование фрагментов HTML кода в шаблонах ActionMailer
Задача: реализовать кэширование фрагментов HTML кода в шаблоне письма для рассылки.
Первое решение которое приходит в голову – это использовать хелпер cache, например так:
<h1>Result has been executed for long time</h1>
<% cache cache_key do %>
<div>
<%= doing_something_long_time_and_show_result %>
</div>
<% end %>
...
Но этот способ не работает, так как ActiveMailer не содержит методы для кэширования. И в результате у нас ошибка:
/Users/undr/.rvm/gems/ruby-1.9.2-p180/gems/actionpack-3.0.7/lib/action_view/helpers/cache_helper.rb:37:in `cache'
...
Второй вариант, это использовать Rails.cache.fetch:
<h1>Result has been executed for long time</h1>
<%= Rails.cache.fetch cache_key do %>
<div>
<%= doing_something_long_time_and_show_result %>
</div>
<% end %>
...
Ошибки уже нет, но результат не верный. В кэш попадает все содержимое шаблона, а не часть в блоке, и, как следствие, в результате письмо содержит дублированные куски HTML кода. То есть сначала выводится заголовок, потом опять заголовок и содержимое блока.
Чтобы убрать дублирование HTML кода в результате, нужно написать примерно такой хелпер:
Rails.cache.fetch(key) do
with_output_buffer(&block)
end
end
И в шаблоне вызывать его.
<h1>Result has been executed for long time</h1>
<%= mailer_cache cache_key do %>
<div>
<%= doing_something_long_time_and_show_result %>
</div>
<% end %>
...
Что же такое Railtie, Engine и Plugin?
Railtie
Railtie – это ядро фреймворка, обеспечивает возможности для расширения Rails и/или изменения процесса инициализации.
Каждый основной компонент Rails (ActionMailer, ActionController, ActionView, ActiveRecord и ActiveResource) является Railtie, так что каждый из них сам несет ответственность за свою инициализацию. Например, это освобождает Rails от каких-либо привязок к ActiveRecord, позволяя другой ORM работать с Rails.
Создание расширений для Rails не требует какой-либо реализации Railtie, но, если Вы хотите взаимодействовать с Rails во время его загрузки или после нее, Railtie – это то, что Вам нужно для такого взаимодействия. Например, чтобы реализовать в плагине одно из ниже перечисленного Вам бы понадобился Railtie:
- создать свои инициализаторы
Rails::Initializable#initializer - конфигурировать Rails или приложение, например чтобы добавить свой генератор
- добавить свои ключи в
config.*для конфигурации среды (environment) - установить подписку на события
ActiveSupport::Notifications добавить rake задачи в Rails
Как тестировать помощники для rails с помощью rspec, использующие методы render(), concat() и capture()?
Когда я писал небольшой плагин для rails, добавляющий в приложение возможность быстрого создания javascript вкладок, у меня возникли трудности с тестированием. Методы плагина, которые использовали методы render(), concat() и capture(), невозможно было нормально протестировать, все время возникали ошибки в самих тестах.
Соответствие MySQL и MongoDB запросов
Эта шпоргалка создана для того чтобы упростить переход с SQL баз данных на MongoDB. В ней остались не затронутыми многие особенности и возможности MongoDB, неимеющие аналогов в SQL, такие как MapReduce, например. Или те о которых я незнаю. Это просто список соответствий MySQL запросов и запросов MongoDb.
Добавление меток и древовидных категорий в Rails приложение на MongoMapper
Продолжение статьи Пример написания приложения на Rails с использованием MongoDB и MongoMapper вместо MySQL и ActiveRecord.
Пример написания приложения на Rails с использованием MongoDB и MongoMapper вместо MySQL и ActiveRecord.
Наше приложение должно уметь сохранять траты за день и выводить статистику по ним за разное время. Траты хранятся в древообразных категориях и им присваюваются метки. Будет облако меток и вывод списка трат для определенной метки. Приложение будет доступно только для зарегистрированных пользователей и данные пользователей будут скрыты друг от друга.
Статистика будет выводиться за определенные периоды в виде графиков и таблиц. Должно быть два варианта статистики: общая и личная. Личная статистика будет учитывать траты конкретного пользователя и будет доступна только ему. Общая статистика будет основана на данных всех пользователей, она будет анонимна и доступна всем. Общая статистика будет ограниченной детализации. В статистике необходимо учесть, какое эмоциональное воздействие оказала трата: положительное (трата принесла радость, удовлетворение), нейтральное (никаких эмоций) или отрицательное (неприятные траты).
Это приложение не ведет баланс, тут не будет прихода. Только расход. Это сервис статистики по тратам.
Два способа ‘eager loading’ в ActiveRecord
Начиная с Rails версии 2.1 в ActiveRecord существует два способа нетерпеливой загрузки (’eager loading’). Первый использует один запрос в котором связывает таблицы оператором JOIN. Второй использует по одному запросу на каждую модель. В Rails версии до 2.1 использовался только первый способ, в версиях начиная с 2.1 используются оба, но второй используется по умолчанию.
Первый способ, обладает некоторыми проблеммами. Он считается медленным, из-за необходимости обрабатывать большое количество избыточных данных (пример 1), особенно при большой вложенности ассоциаций для загрузки, и используется только если в запросе необходимо использовать поля ассоциаций (например в параметре :conditions)


(15 голосов, средний: 4.73 из 5)