Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails Rails-我应该在模型级别还是在db级别定义默认属性值?_Ruby On Rails_Ruby - Fatal编程技术网

Ruby on rails Rails-我应该在模型级别还是在db级别定义默认属性值?

Ruby on rails Rails-我应该在模型级别还是在db级别定义默认属性值?,ruby-on-rails,ruby,Ruby On Rails,Ruby,在rails中,我们可以使用gem'default\u value\u for'中的一条宏语句或自己定义模型级别的默认属性值。另一方面,我们可以使用迁移“default”选项在数据库级别定义它。我不知道哪种是rails的最佳实践,或者在不同的场景中应该使用哪种方式 任何回复都将不胜感激你可能想考虑的事情。 当您在应用程序中设置默认值时 默认值可以很容易地更改,并且 默认值可以是动态的,也可以是动态的 有一些方法可以绕过默认设置 当您在数据库中设置默认值时 更改默认值需要迁移(对于大型表可能

在rails中,我们可以使用gem'default\u value\u for'中的一条宏语句或自己定义模型级别的默认属性值。另一方面,我们可以使用迁移“default”选项在数据库级别定义它。我不知道哪种是rails的最佳实践,或者在不同的场景中应该使用哪种方式


任何回复都将不胜感激你可能想考虑的事情。

当您在应用程序中设置默认值时

  • 默认值可以很容易地更改,并且
  • 默认值可以是动态的,也可以是动态的
  • 有一些方法可以绕过默认设置
当您在数据库中设置默认值时

  • 更改默认值需要迁移(对于大型表可能会有什么问题)
  • 实现动态默认值和
  • 无法绕过应用程序中的默认设置(更安全)

您可能要考虑的另一个选项是重写属性吸收器方法。这种方法仅在从数据库返回空值(或无效值)时使用默认值,不会改变存储新值的方式

def foo
  super || 'a default value'
end

在数据库中设置默认值通常更可取,因为ActiveRecord是围绕约定而非配置方法构建的,在这种方法中,数据库表驱动模型,而不是相反

但是,数据库默认值不是很聪明-它们将始终被应用,并且始终具有相同的静态值*(除非您更改DB模式)。在大多数情况下,这并不重要

但是,如果默认值需要某种计算,例如通过基于IP的地理位置设置用户的默认国家/地区,则需要在应用程序级别(模型)上设置默认值

其他例子包括:

  • 存储序列化数据的列(非本机JSON列)
  • 应该默认为某个记录的关系
在应用程序中,您在哪里设置默认值? 在模型中 最简单的示例是使用模型回调:

class Thing 
  after_initialize :set_defaults, if: :new_record?

  private
    def set_defaults
      self.foo = 'bar'
    end
end
模型回调的缺点是很难精确地控制它在应用程序流中发生的位置。例如,如果初始化块很昂贵,您不希望它发生在所有测试中

在控制器中 如果默认值依赖于请求的上下文,例如使用Geocoder进行基于IP的地理定位的示例:

class User < ActiveRecord::Base
  def set_default_location(geo)
    u.city    = geo.city
    u.zipcode = geo.postal_code
    u.country = geo.country_code
  end
end

class UserController
  def new
    @user = User.new do |u|
      u.set_default_location(request.safe_location)
    end
  end
end

我会根据您想要设置为默认值的数据来说明何时使用它,何时不使用它


如果您想将静态值设置为默认值,例如:
false,0,user
,如果您想将动态值设置为默认值。如果是随机生成的UUID,或者是相对于创建日期发生变化的日期,那么您可以使用
default\u值作为
gem。

请参见Hi@max谢谢您的回答。您能否详细说明原因:“将太多的业务逻辑放在ORM类(ActiveRecord::Base的子类)中会导致违反单一责任原则”?因为它们有大量的责任——验证、类型转换、持久性、脏状态跟踪,i18n等。只是rails将其折叠起来,所以它在前面不明显。*这不完全正确。例如,Postgres允许您使用用户创建的函数来设置默认值。但是,应用程序中已知的内容与数据库中已知的内容之间存在差异。
module ManagerFactory
  def self.new(attributes = {})
    user = User.new(attributes)
    user.add_role(:manager)
    user
  end
end