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