В Rails 4 введен ActiveRecord::QueryMethods.none, который реализует паттерн null oject. Он используется в экземплярах, где у вас есть метод, который возвращает relation, но есть условие, в котором вы не хотите, чтобы был произведен запрос к базе данных. Все последующие условия в цепочке будут работать без проблемы, избавляя от необходимости постоянно проверять, работает ли объект ваш с relation.
Team.none.where(name: 'Justice League')
# => #
Для скоупов (scopes) требуются вызываемые объекты
Скоупы (scopes) всегда были поводом расстройства для новых разработчиков Rails. Наибольшая проблема в том, что выражение скоупа, определенного не через lambda, вычисляется при инициализации. Пример этого - базируемые на временных интервалах:
Любой будущий вызов всегда будет определять записи, опубликованные за 2 недели до начальной инициализации объекта, но не текущего времени.
В Rails 4 все скоупы должны быть вызываемым объектом, таким как Proc или lambda:
class Team < ActiveRecord::Base
scope :active, -> { where(status: 'active') }
end
Убран IdentityMap
Так как у IdentityMap были некоторые несоответствия с ассоциациями, которые никогда не разрешались, он был удален из Rails 4. Это может возвратиться однажды, если проблемы будут устранены. Если Вы обновляете Rails 3 приложения, пожалуйста удалите active_record.identity_map = true из файла конфигурации config/application.rb.
destroy!
В ActiveRecord теперь есть метод #destroy!. Если запись не может быть уничтожена, исключение ActiveRecord::RecordNotDestroyed будет иницировано.
update_columns
В ActiveRecord есть два новых метода #update_columns и #update_column. При вызове этих методов будут обновлены атрибут(ы) модели, пропуская валидацию и вызов callbacks-методов.
Больше не поддерживается выполнение Model.all, которое исполняется немедленно и возвращает массив записей. В Rails 4 вызов Model.all эквивалентно вызову (ныне устаревшего) Model.scoped. Это подразумевает, что множество зависимостей и условий могут быть объеденены в цепочку Model.all и результат будет вычислен "лениво" (по запросу) (lazily). Model.all возвращает Relation. Если вы все же хотите получить массив записей, используйте Model.all.to_a.
Сортировка по умолчанию добавлена в first
При вызове first в предыдущих версиях Rails в запросе просто добавлялось LIMIT 1. Это не гарантировало того, что будет возвращена запись с наименьшим первичным ключем.
Вызов first в Rails 4 будет добавляь явный порядок сортировки в запросе, что гарантирует, что будет возвращена запись с наименьшим первичным ключем.
Team.first
Rails 3: SELECT "teams".* FROM "teams" LIMIT 1
Rails 4: SELECT "teams".* FROM "teams" ORDER BY "teams"."id" ASC LIMIT 1
Устаревшие динамические методы поиска
В предыдущих версиях Rails ActiveRecord обеспечивал метод поиска для каждого поля в вашей таблице базы данных. Например, если у вас есть поле email в модели User, вы можете использовать: User.find_by_email('some@emailaddress.com') или User.find_all_by_email('some@emailaddress.com'). Более того, вы могли объеденить в запросе несколько полей, указав в названии метода and между названиями полей.
Динамические методы поиска объявлены полностью устаревшими в Rails 4.
Примеры замены устаревших динамических методов поиска в Rails 4:
Метод поиска основанный на использовании хэша также объявлен устаревшим. Если вы уже использовали новый стиль, представленный в Rails 3, это не должно повлиять на ваш код.
Метод #pluck позволяет вам выбрать значения одного поля и вернуть результат в виде массива значений полея записей таблицы. В Rails 4 вы можете указать множество полей для выборки, используя #pluck:
Метод запроса .includes предназначается для нетерпеливой загрузки ассоциаций. Некоторые разработчики используют .includes метод, чтобы выполнить некоторые запросы LEFT OUTER JOIN на ассоциациях, используя строковые отрывки SQL. В Rails 4, при добавлении строкового условия включенной ассоциации приводит к выдаче предупреждения.
Вот пример, который выбирает все Teams, у которых есть элемент по имени Batman:
Team.includes(:members).where('members.name = ?', 'Batman')
# Rails 3
SQL (0.7ms) SELECT "teams"."id" AS t0_r0, "teams"."name" AS t0_r1, "teams"."created_at" AS t0_r2, "teams"."updated_at" AS t0_r3, "members"."id" AS t1_r0, "members"."name" AS t1_r1, "members"."bio" AS t1_r2, "members"."team_id" AS t1_r3, "members"."created_at" AS t1_r4, "members"."updated_at" AS t1_r5 FROM "teams" LEFT OUTER JOIN "members" ON "members"."team_id" = "teams"."id" WHERE (members.name = 'Batman')
# Rails 4
DEPRECATION WARNING: It looks like you are eager loading table(s) (one of: teams, members) that are referenced in a string SQL snippet.
...
В то время как запрос все еще выполняется в Rails 4, рекомендуется включать новый метод запроса ActiveRecord::QueryMethods.references вместо этого:
Паттерн Null Object
В Rails 4 введен
ActiveRecord::QueryMethods.none
, который реализует паттернnull oject
. Он используется в экземплярах, где у вас есть метод, который возвращаетrelation
, но есть условие, в котором вы не хотите, чтобы был произведен запрос к базе данных. Все последующие условия в цепочке будут работать без проблемы, избавляя от необходимости постоянно проверять, работает ли объект ваш сrelation
.Для скоупов (scopes) требуются вызываемые объекты
Скоупы (scopes) всегда были поводом расстройства для новых разработчиков Rails. Наибольшая проблема в том, что выражение скоупа, определенного не через
lambda
, вычисляется при инициализации. Пример этого - базируемые на временных интервалах:Любой будущий вызов всегда будет определять записи, опубликованные за 2 недели до начальной инициализации объекта, но не текущего времени.
В Rails 4 все скоупы должны быть вызываемым объектом, таким как
Proc
илиlambda
:Убран IdentityMap
Так как у
IdentityMap
были некоторые несоответствия с ассоциациями, которые никогда не разрешались, он был удален из Rails 4. Это может возвратиться однажды, если проблемы будут устранены. Если Вы обновляете Rails 3 приложения, пожалуйста удалитеactive_record.identity_map = true
из файла конфигурацииconfig/application.rb
.destroy!
В
ActiveRecord
теперь есть метод#destroy!
. Если запись не может быть уничтожена, исключениеActiveRecord::RecordNotDestroyed
будет иницировано.update_columns
В
ActiveRecord
есть два новых метода#update_columns
и#update_column
. При вызове этих методов будут обновлены атрибут(ы) модели, пропуская валидацию и вызов callbacks-методов.Model.all
Больше не поддерживается выполнение
Model.all
, которое исполняется немедленно и возвращает массив записей. В Rails 4 вызовModel.all
эквивалентно вызову (ныне устаревшего)Model.scoped
. Это подразумевает, что множество зависимостей и условий могут быть объеденены в цепочкуModel.all
и результат будет вычислен "лениво" (по запросу) (lazily).Model.all
возвращаетRelation
. Если вы все же хотите получить массив записей, используйтеModel.all.to_a
.Сортировка по умолчанию добавлена в first
При вызове
first
в предыдущих версиях Rails в запросе просто добавлялосьLIMIT 1
. Это не гарантировало того, что будет возвращена запись с наименьшим первичным ключем.Вызов
first
в Rails 4 будет добавляь явный порядок сортировки в запросе, что гарантирует, что будет возвращена запись с наименьшим первичным ключем.Устаревшие динамические методы поиска
В предыдущих версиях Rails
ActiveRecord
обеспечивал метод поиска для каждого поля в вашей таблице базы данных. Например, если у вас есть полеemail
в моделиUser
, вы можете использовать:User.find_by_email('some@emailaddress.com')
илиUser.find_all_by_email('some@emailaddress.com')
. Более того, вы могли объеденить в запросе несколько полей, указав в названии метода and между названиями полей.Динамические методы поиска объявлены полностью устаревшими в Rails 4.
Примеры замены устаревших динамических методов поиска в Rails 4:
Метод поиска основанный на использовании хэша также объявлен устаревшим. Если вы уже использовали новый стиль, представленный в Rails 3, это не должно повлиять на ваш код.
Детали: activerecord-deprecated_finders.
Пример использования вместо устаревшего метода поиска с использованием
ActiveRecord::QueryMethods
:find_by и find_by!
Новые методы поиска (взамен устаревших) были добавлены в Rails 4:
Множество полей с помощью pluck
Метод
#pluck
позволяет вам выбрать значения одного поля и вернуть результат в виде массива значений полея записей таблицы. В Rails 4 вы можете указать множество полей для выборки, используя#pluck
:References
Метод запроса
.includes
предназначается для нетерпеливой загрузки ассоциаций. Некоторые разработчики используют.includes
метод, чтобы выполнить некоторые запросыLEFT OUTER JOIN
на ассоциациях, используя строковые отрывки SQL. В Rails 4, при добавлении строкового условия включенной ассоциации приводит к выдаче предупреждения.Вот пример, который выбирает все Teams, у которых есть элемент по имени Batman:
В то время как запрос все еще выполняется в Rails 4, рекомендуется включать новый метод запроса
ActiveRecord::QueryMethods.references
вместо этого:Однако, если вы использовали синтаксис хеша с условиями ассоциации, он все еще выполнит
LEFT OUTER JOIN
без любых предупреждений:Кроме того, упорядочивание с помощью строковых отрывков SQL на включенных ассоциациях будет все еще работать без необходимости указания
references
: