在rails中,我们可以使用gem'default_value_for'或selfelf中的一个宏语句在模型级别定义默认属性值。另一方面,我们可以使用迁移'default'选项在数据库级别定义它。我很困惑哪个是rails的最佳实践,或者我们应该在不同场景中使用哪种方式?
任何回复都表示赞赏! :d
答案 0 :(得分:2)
设置数据库中的默认值通常更可取,因为ActiveRecord是围绕约定优于配置方法构建的,其中数据库表驱动模型 - 而不是相反。
但是,数据库默认值不是非常智能 - 它们将始终应用并始终具有相同的静态值*(除非您更改数据库架构)。在大多数情况下,这并不重要。
但是,如果默认值需要某种计算,例如通过基于IP的地理位置设置用户的默认国家/地区,则需要在应用程序级别(模型)上设置默认值。
其他例子如下:
最简单的例子是使用模型回调:
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
如果不仔细检查,这可能会导致控制器膨胀。
有人会争辩说,将过多的业务逻辑放在ORM类(ActiveRecord::Base
的子类)中会导致违反单一责任原则,并使您的应用程序过于脆弱。
module ManagerFactory
def self.new(attributes = {})
user = User.new(attributes)
user.add_role(:manager)
user
end
end
答案 1 :(得分:1)
您可能想要考虑的事情。
在应用程序中设置默认值时:
在数据库中设置默认值时:
您可能需要考虑的另一个选项是覆盖属性getter方法。此方法仅在从数据库返回空(或无效值)时使用默认值,它不会更改存储新值的方式。
def foo
read_attribute(:foo) || 'a default value'
end
答案 2 :(得分:0)
我会说何时使用它以及何时不根据您想要设置为默认值的数据使用它。
如果您想到的是要设置为默认值的静态值,例如:false, 0, user
,如果您想要将某些动态设置为默认值。生命随机generated UUID
或相对于创建日期而改变的日期,您可以使用default_value_for
gem。