Я пытаюсь найти лучший способ установить значения по умолчанию для объектов в Rails.
Лучшее, что я могу придумать, - это установить значение по умолчанию в new
методе контроллера.
Есть ли у кого-нибудь какие-либо комментарии, если это приемлемо или есть лучший способ сделать это?
ruby-on-rails
ruby
biagidp
источник
источник
Ответы:
«Правильный» - опасное слово в Ruby. Обычно есть несколько способов сделать что-либо. Если вы знаете, что вам всегда нужно это значение по умолчанию для этого столбца в этой таблице, установить их в файле миграции БД - самый простой способ:
Поскольку ActiveRecord автоматически обнаруживает свойства вашей таблицы и столбца, это приведет к установке того же значения по умолчанию для любой модели, использующей его в любом стандартном приложении Rails.
Однако, если вы хотите, чтобы значения по умолчанию устанавливались только в определенных случаях - скажем, это унаследованная модель, которая разделяет таблицу с некоторыми другими, - тогда еще один элегантный способ - сделать это прямо в вашем коде Rails при создании объекта модели:
Затем, когда вы выполняете a
GenericPerson.new()
, атрибут "Doe" всегда будет повышаться до,Person.new()
если вы не замените его чем-то другим.источник
.new
методом класса. В этом сообщении блога обсуждение прямого вызова ActiveRecord касалось.allocate
объектов модели, загруженных с существующими данными из базы данных. ( И это ужасная идея для ActiveRecord работать таким образом, IMO. Но это не относится кchange_column_default :people, :last_name, nil
stackoverflow.com/a/1746246/483520change_column :people, :last_name, :string, default: "Doe"
Основываясь на ответе SFEley, вот обновленный / исправленный для новых версий Rails:
источник
change_column
может быть вполне «структурирование», обратная операция не может быть выведена. Если вы не уверены, просто протестируйте его, запустивdb:migrate
иdb:rollback
сразу после этого. Принятый ответ - тот же результат, но по крайней мере предполагаемый!up
иdown
как описано выше от @GoBustoВо-первых, нельзя перегружать, так
initialize(*args)
как он вызывается не во всех случаях.Лучше всего использовать настройки по умолчанию при миграции:
Второй вариант - поместить в модель значения по умолчанию, но это будет работать только с атрибутами, которые изначально равны нулю. У вас могут возникнуть проблемы, как у меня со
boolean
столбцами:Вам нужно,
new_record?
чтобы значения по умолчанию не переопределяли значения, загруженные из базы данных.Вам нужно
||=
запретить Rails переопределять параметры, переданные в метод инициализации.источник
after_initiation :your_method_name
.... 2 использованияself.max_users ||= 10
after_initialize do
вместоdef after_initialize
Вы также можете попробовать
change_column_default
свои миграции (проверено в Rails 3.2.8):change_column_default Документы по API Rails
источник
Если вы имеете в виду объекты ActiveRecord, у вас есть (более) два способа сделать это:
1. Используйте параметр: default в БД.
НАПРИМЕР
Подробнее здесь: http://api.rubyonrails.org/classes/ActiveRecord/Migration.html
2. Используйте обратный вызов
НАПРИМЕР
before_validation_on_create
Подробнее здесь: http://api.rubyonrails.org/classes/ActiveRecord/Callbacks.html#M002147
источник
В Ruby on Rails v3.2.8, используя
after_initialize
обратный вызов ActiveRecord, вы можете вызвать метод в своей модели, который назначит значения по умолчанию для нового объекта.Итак, ИМО это должно выглядеть примерно так:
Foo.bar = default_value
для этого экземпляра, если он не содержитattribute_whose_presence_has_been_validated
ранее при сохранении / обновлении.default_value
Будет использоваться в сочетании с вашей точки зрения , чтобы сделать форму , используяdefault_value
дляbar
атрибута.В лучшем случае это хакерство ...
ИЗМЕНИТЬ - использовать 'new_record?' чтобы проверить, создается ли экземпляр из нового вызова
Вместо проверки значения атрибута используйте
new_record?
встроенный метод с рельсами. Итак, приведенный выше пример должен выглядеть так:Это намного чище. Ах, магия Rails - она умнее меня.
источник
after_initialize
обратный звонок здесь? В документации Rails по обратным вызовам есть пример установки значения по умолчаниюbefore_create
без дополнительных проверок условийSubscription
after_initialize
вместоbefore_create
обратного вызова, заключается в том, что мы хотим установить значение по умолчанию для пользователя (для использования в представлении), когда они создают новые объекты.before_create
Обратный вызов вызывается после того, как пользователь был отслужен новый объект, при условии их ввода, и представил объект для создания контроллера. Затем контроллер проверяет наличиеbefore_create
обратных вызовов. Это кажется нелогичным, но это предмет номенклатуры -before_create
относится кcreate
действию. Создание экземпляра нового объекта неcreate
является объектом.По крайней мере, для логических полей в Rails 3.2.6 это будет работать при вашей миграции.
Установка
1
или0
для значения по умолчанию здесь не сработает, поскольку это логическое поле. Это должно быть значениеtrue
илиfalse
.источник
Если вы имеете дело с моделью, вы можете использовать API атрибутов в Rails 5+ http://api.rubyonrails.org/classes/ActiveRecord/Attributes/ClassMethods.html#method-i-attribute
просто добавьте миграцию с правильным именем столбца, а затем в модели установите его с помощью:
источник
Сгенерируйте миграцию и используйте
change_column_default
кратко и обратимо:источник
Если вы просто устанавливаете значения по умолчанию для определенных атрибутов модели, поддерживаемой базой данных, я бы подумал об использовании значений столбцов sql по умолчанию - можете ли вы уточнить, какие типы значений по умолчанию вы используете?
Есть несколько подходов к этому, этот плагин выглядит интересным вариантом.
источник
Предложение переопределить новый / инициализировать, вероятно, неполное. Rails (часто) вызывает allocate для объектов ActiveRecord, и вызовы allocate не приводят к вызовам инициализации.
Если вы говорите об объектах ActiveRecord, обратите внимание на переопределение after_initialize.
Эти сообщения в блоге (не мои) полезны:
Значения по умолчанию Конструкторы по умолчанию не вызываются
[Edit: SFEley указывает, что Rails действительно смотрит на значение по умолчанию в базе данных, когда создает экземпляр нового объекта в памяти - я этого не осознавал.]
источник
Мне нужно было установить значение по умолчанию, как если бы оно было указано в качестве значения столбца по умолчанию в БД. Так он ведет себя вот так
Поскольку обратный вызов after_initialize вызывается после установки атрибутов из аргументов, не было возможности узнать, равен ли атрибут нулю, потому что он никогда не устанавливался или был намеренно установлен как ноль. Так что мне пришлось немного покопаться и прийти с этим простым решением.
У меня отлично работает. (Рельсы 3.2.x)
источник
Потенциально даже лучший / более чистый потенциальный способ, чем предложенные ответы, - это перезаписать аксессор, например:
См. «Перезапись средств доступа по умолчанию» в документации ActiveRecord :: Base и другие материалы из StackOverflow об использовании self .
источник
Я ответил на аналогичный вопрос здесь ... чистый способ сделать это - использовать Rails attr_accessor_with_default
ОБНОВИТЬ
attr_accessor_with_default устарел в Rails 3.2 .. вы можете сделать это вместо этого с чистым Ruby
источник
attr_accessor_with_default
устарело с rails> 3.1.0Если вы говорите об объектах ActiveRecord, я использую гем "attribute-defaults".
Документация и загрузка: https://github.com/bsm/attribute-defaults
источник
Вы можете использовать гем rails_default_value. например:
https://github.com/keithrowell/rails_default_value
источник
Вы можете переопределить конструктор для модели ActiveRecord.
Как это:
источник