【问题标题】:Default values for models in railsrails 中模型的默认值
【发布时间】:2015-04-11 07:24:39
【问题描述】:

在迁移或回调中设置默认值更好吗?在迁移中很难删除(或设置另一个)默认值,但在模型中又多了一段代码

【问题讨论】:

    标签: ruby-on-rails ruby activerecord rails-activerecord


    【解决方案1】:

    在迁移中定义默认值也有一些缺点。当您只调用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 
    

    【讨论】:

    • 为什么不before_create?那么你不需要检查:persisted?
    • @WojciechBednarski,因为before_create 将覆盖现有值,如果对象已经有值,我们不想设置默认值。这就是为什么我们仅在对象是新对象且未持久化时才设置默认值的原因。
    • before_create 在数据库行中的模型生命周期中只会触发一次。每次更改 DB 中的模型时,before_update 都会启动。
    • @SharvyAhmed 谢谢您,先生,我注意到您的答案正在从模型中验证。也可以直接从创建控制器设置值。您如何看待这种方法?
    • @SharvyAhmed 但是在迁移中使用默认值确实适用于Model.new
    【解决方案2】:

    在 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
    

    【讨论】:

    • 值得注意的是,Rails Attributes API 将允许 "",一个空字符串,与这个模型一样。
    • 太棒了。好处是它也接受proc!是否也需要将其添加到迁移中?
    【解决方案3】:

    捎带@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 
    

    【讨论】:

      【解决方案4】:

      作为一般规则,在后端,在模型和数据库中实施约束。这就像验证 JS 而不是在后端验证(PHP、ROR 等)。有人可以修改您的 JS 以通过验证,并且由于您没有在后端进行验证,您的网站可能会受到损害。因此,始终在双方进行验证,至少如果您的应用服务器受到攻击,数据库服务器可能会采取一些防御措施。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-06-17
        • 2014-01-21
        • 1970-01-01
        • 2018-10-22
        • 2015-12-31
        • 1970-01-01
        相关资源
        最近更新 更多