Rails Draper 的装饰器导致 ArgumentError

Posted

技术标签:

【中文标题】Rails Draper 的装饰器导致 ArgumentError【英文标题】:Rails Draper's Decorator caused ArgumentError 【发布时间】:2022-01-17 12:35:44 【问题描述】:

我为 Rails 项目设置了 Draper 的装饰器来替换原来的助手。我将帮助代码移到了装饰器:

def birthday(date)
  "MinYear#date.year - 1911 Month#date.month Day#date.day"
end

并在 View 中添加 .decorate 文本以使用它

<%= user.decorate.birthday %>

但是,这会导致ArgumentError wrong number of arguments (given 0, expected 1)

def birthday(date)

如果我删除第一个日期,它将显示NoMethodError undefined method 'date' for #&lt;UserDecorator:0x000055570cbafc58&gt;

"MinYear#date.year - 1911 Month#date.month Day#date.day"

如何解决这些错误?

【问题讨论】:

date 是在哪里定义的?这是 User 模型上的一个属性? 用户模型def age Date.today.year - birthday.year end上定义的日期 【参考方案1】:

引发ArgumentError 是因为您调用birthday 而不传入date。 执行&lt;%= user.decorate.birthday(Date.current) %&gt; 将使错误消失。

但是,这可能不是您想要的,因为 date 是在 User 模型中定义的。

装饰东西最简单的方法是使用delegate_all。它将使来自 User 模型的所有方法在装饰器中可用。

class UserDecorator < Draper::Decorator
  delegate_all
  
  def birthday
   "MinYear#date.year - 1911 Month#date.month Day#date.day"
  end
end

请注意,装饰器中声明的任何方法都将覆盖模型中声明的方法,在您的情况下为birthday。例如,如果装饰器中有其他调用birthday 的方法,它将使用装饰器中的方法,而不是模型中的方法,通过调用model.birthday 可以使用。

另一种方法是调用model 对象上的方法:

class UserDecorator < Draper::Decorator
  def date
    model.date
  end

  def birthday
   "MinYear#date.year - 1911 Month#date.month Day#date.day"
  end
end

【讨论】:

非常感谢我使用 decorates_association :user 而不是 delegate_all ,这是一个好习惯吗?谢谢 你为什么会有decorates_association :user,这对我来说毫无意义。定义了birthday 的装饰器看起来如何?对于User 模型,通常应该存在UserDecoratordecorates_association :user 表示您在 User 模型内有一个名为 user 的关联。 我确实在用UserDecorator,发现两种写法都有效 我主要使用delegate_all。我不认为有好的或坏的做法,但可能有人会说,如果一个模型有大量的方法并且使用了delegate_all,它将使所有方法都可用,即使它们中的大多数都没有使用。 有时间请看一下,***.com/help/someone-answers。谢谢。

以上是关于Rails Draper 的装饰器导致 ArgumentError的主要内容,如果未能解决你的问题,请参考以下文章

ruby 在draper装饰器中进行I18n懒惰查找

rspec 使用 draper Decorator 测试视图

Ruby on Rails 模式 - 装饰器与演示器

字符串装饰器类导致大量构建错误

Python 分析:使用 line_profiler 的 @profile 装饰器会导致错误

设计模式之装饰器