web-dev-qa-db-ja.com

railsのモデルのデフォルト値

移行またはコールバックでデフォルト値を設定する方が良いですか?移行時にデフォルト値を削除(または別の設定)することは困難ですが、モデルではもう1つのコードを使用します

13
Denis Papushaev

移行でデフォルトを定義することには、いくつかの欠点もあります。 Model.newを呼び出すだけでは、これは機能しません。

after_initialize コールバックを作成することを好みます。これにより、デフォルトの属性を設定できます。

class Model < ActiveRecord::Base
  after_initialize :set_defaults, unless: :persisted?
  # The set_defaults will only work if the object is new

  def set_defaults
    self.attribute  ||= 'some value'
    self.bool_field = true if self.bool_field.nil?
  end
end 
27
Sharvy Ahmed

Rails 5、 attributes API では、デフォルト値を指定できます。構文は単純で、移行せずにデフォルトを変更できます。

# db/schema.rb
create_table :store_listings, force: true do |t|
  t.string :my_string, default: "original default"
end

# app/models/store_listing.rb
class StoreListing < ActiveRecord::Base
  attribute :my_string, :string, default: "new default"
end
17
w_hile

原則として、バックエンドでは、モデルとDBに制約を適用します。これは検証JSのようなもので、バックエンド側(PHP、RORなど)では検証されません。誰かがJSを変更して検証に合格する可能性があります。バックエンドで検証しなかったため、サイトが危険にさらされている可能性があります。したがって、少なくともアプリサーバーが危険にさらされた場合は、DBサーバーが何らかの防御策を講じる可能性があります。

1
Abraham

@ w-hileの答えに便乗します—「設定」したいものがたくさんない限り、これは素晴らしい答えです—

設定に捧げられた多数の列でモデルを汚染することにうんざりして疲れてきたので、 Setsy と書きました。

class User < ApplicationRecord

  include ::Setsy::DSL

  # each setting can be a hash, like posts_limit, or just a value
  DEFAULT_SETTINGS = {
    posts_limit: { value: 10 },
    favorite_color: 'blue'
  }.freeze

  setsy :settings, column: :settings_data, defaults: DEFAULT_SETTINGS do |conf|
    conf.reader :posts_limit_and_color do
      "posts limit is #{posts_limit} and color is #{favorite_color}"
    end
  end
end

そして、次のことができます、

user = User.first
user.settings # {posts_limit: 10, favorite_color: 'blue'}
user.settings.posts_limit # 10
user.settings.posts_limit.default? # true 
user.assign_attributes(settings_data: { posts_limit: 15, favorite_color: 'blue' })
user.settings.posts_limit.default? # false 
user.settings.posts_limit.default # 10 
1
Josh Brody