【问题标题】:Ruby on rails return a string if a model attribute is nil如果模型属性为 nil,Ruby on rails 返回一个字符串
【发布时间】:2018-01-15 10:17:04
【问题描述】:

我有一个用户模型,它有一个配置文件。个人资料具有姓名、性别、年龄、出生日期、职称等属性。配置文件中没有必填字段。 用户由管理员仅通过电子邮件地址和密码创建。创建用户时,所有配置文件字段均为零。创建用户后,他可以注册并编辑他的个人资料。当我们转到用户个人资料时,我想显示用户详细信息,如果未设置详细信息,我想显示“未设置”。

首选方法是覆盖配置文件模型中的属性,例如:

def name
  super || 'not set'
end
def age
  super || 'not set'
end
//and so on 

但这样做会产生大量代码重复。 在视图中做<%= @user.name || 'not set'%>也会导致很多代码重复。

我曾考虑将“未设置”作为迁移中所有属性的默认值,但有些字段是整数和日期,因此不可行,而且我们无法添加翻译。

我查看了 ActiveRecord 属性并尝试将默认值设置为我的字符串

class Profile < ApplicationRecord
attribute :name, :string, default: "not set"

但这与在 rails 迁移中分配默认值相同,并且不适用于其他数据类型。

我希望有一种方法可以做类似的事情

def set_default(attribute)
  attribute || 'not set'
end

这样的场景一定很常见,但我很惊讶在 stackoverflow 或其他地方没有发现任何与此相关的问题。我google了很多,但找不到解决方案。任何链接也非常感谢。

【问题讨论】:

  • 我认为使用 gem 来做这件事有点矫枉过正
  • 您的个人资料视图如何?

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


【解决方案1】:

也许是一些元编程?

class YourModel
  %w(name age).each do |a| # Add needed fields
    define_method(a) do
      super() || 'not set'
    end
  end
end

这可以提取到一个关注点,并将其包含在您需要的地方。

【讨论】:

  • 我试过这样:%w(name age dob).each do |a| define_method(a) 做超级 || 'not set' end end 但我收到一个错误:implicit argument passing of super from method defined by define_method() is not supported. Specify all arguments explicitly
  • 抱歉,这需要使用显式括号调用super(),错过了。
【解决方案2】:

我建议不要在模型中设置默认值。使用 Presenter/Decorator 来显示 UI 的默认值。

这是 Draper (https://github.com/drapergem/draper) 的示例,但还有其他装饰器库,您甚至可以编写一个基本的装饰器而不添加依赖项:

class ProfileDecorator < Draper::Decorator
  DEFAULT = "not set".freeze
  def name
    model.name || DEFAULT
  end
end

# and then use it like:

profile.decorate.name 

至于重复:大多数时候我更喜欢重复而不是元编程。恕我直言,更易于调试、阅读、查找和理解。

【讨论】:

  • 这是一个很好的建议,但更多的是评论而不是答案。也许你可以添加一个例子?
  • 你当然是对的,@Stefan :-)。添加了一个示例。
  • 感谢@pascal 的建议。完全同意元编程更难调试和理解(+我对rails很陌生)。如果我错了,请纠正我;如果我们既有逻辑又有观点,那么装饰者或演示者会更可取,在这种情况下,我认为没有太多逻辑,使用 gem(draper) 只是为了解决这个问题将是“过度反应”。此外,解决这个问题的元编程非常简单明了,所以我想我会坚持 Predos 的回答。不过非常感谢。
  • @sonm10 是的,我使用装饰器来提取与视图相关的逻辑(并且具有默认值是逻辑,恕我直言)。我将它们视为与模型绑定的助手。我的模型通常纯粹用于数据库访问,不包含太多其他内容。如果这是你唯一需要装饰器的地方,那么添加一个 Gem/Dependency 可能有点过头了,你是对的。我仍然会跳过元编程并在普通的 ruby​​ 中添加这些方法。
猜你喜欢
  • 2013-06-15
  • 1970-01-01
  • 2017-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-09
相关资源
最近更新 更多