【问题标题】:Ruby (Rails) Delegate attributes to another model's method?Ruby(Rails)将属性委托给另一个模型的方法?
【发布时间】:2011-01-16 02:02:03
【问题描述】:

-编辑-

从第一个答案中阅读了 Delegate 方法后,我的问题是,是否可以将两种不同的方法委托给另一个方法。

IE:我目前有:@photo.attachment.file.url、@photo.attachment.height 和 @photo.attachment.width

我希望能够通过@photo.file.url、@photo.file.height、@photo.file.width 访问所有这些。

语法的原因是Attachment是一个使用Paperclip管理文件的模型,Paperclip是生成.file方法的(模型叫做Attachment,模型使用Paperclip的has_attached_file :file)。

-原始问题-

我想知道 Ruby 中的别名方法和属性(我认为这是一个通用的 ruby​​ 问题,尽管我的应用程序是在 Rails 3 中):

我有两个模型:Photo has_one Attachment。

附件具有“高度”和“宽度”属性,以及“文件”方法(来自 Paperclip)。

所以默认情况下我可以像这样访问附件模型的位:

photo.attachment.width # returns width in px
photo.attachment.height # returns height in px
photo.attachment.file # returns file path
photo.attachment.file.url #returns url for the default style variant of the image
photo.attachment.file.url(:style) #returns the url for a given style variant of the image

现在,在我的照片类中,我创建了这个方法:

def file(*args)
    attachment.file(*args)
end

所以,现在我可以简单地使用:

photo.file # returns file path
photo.file.url # returns file url (or variant url if you pass a style symbol)

我的问题是,我可以将photo.attachment.file 直接指向photo.file,但我也可以将高度和宽度映射到photo.file,这样,为了保持一致性,我可以访问高度和宽度属性通过photo.file.heightphoto.file.width?

这样的事情有可能吗?如果有,它是什么样子的?

【问题讨论】:

  • 为什么不直接将 Photo#height 委托给 Attachment#height?为什么要打扰 photo.file.height?
  • 只是为了保持一致性。 Photo.height 很好,但如果所有与文件相关的命令都在 Photo.file 下,那么至少对我来说更适合 Least Surprise 的 Principal。另外,只是好奇是否可以做到。
  • 为什么不被接受? Rails 委托方法是这里的答案,对吗?那有什么问题?
  • 也许我在这里没有理解某些东西,但我想知道我是否可以将@photo.attachment.height(其中height 是附件模型的一个属性)委托给@photo.file.height,其中file 是插件提供的方法。根据给出的答案,我不明白如何做到这一点,我也无法自己推断出来。所以,如果你能回答这个问题,你就会得到赏金:)
  • 关于您的编辑,与方法相比,ruby 没有单独的属性概念。它们都只是方法。

标签: ruby-on-rails ruby-on-rails-3 alias shortcut


【解决方案1】:

所以你要问的是

photo.file       --> photo.attachment.file
photo.file.url   --> photo.attachment.file.url
photo.file.width --> photo.attachment.width

您无法通过委托解决此问题,因为您希望 file 根据接下来的内容具有不同的含义。要实现这一点,您需要重新打开回形针,我不建议这样做(因为我相信 api 本身就很好)。

我能想到的解决这个问题的唯一方法就是添加消除file 级别。像这样:

photo.width      --> photo.attachment.width
photo.file       --> photo.attachment.file
photo.url        --> photo.attachment.file.url

然后,您可以通过为每个想要的方法使用 delegate 来解决这个问题。

所以你写

class Photo
  delegate :width, :height, :file, :to => :attachment
  delegate :url,   :to => :'attachment.file'
end

希望这会有所帮助。

【讨论】:

  • “你不能用委托解决这个问题,因为你希望那个文件根据接下来的内容来代表不同的东西。”这就是答案。谢谢!我认为您的方式可能是最好的,尽管它确实涉及一些重写。感谢您的回答!
【解决方案2】:

您可以使用 Rails 的“委托”方法。看看我对这个问题的回答:

What is a more Ruby-like way of doing this command?

【讨论】:

  • 很好的建议!我以前从未见过“代表”!你有一个例子说明我如何将附件专门委托给photo.file,而不仅仅是photo
【解决方案3】:

想到的最简单的方法是将附件中的 url 方法委托给文件:

class Attachment < ActiveRecord::Base
  delegate :url, :to => :file
end

这样你就可以调用 photo.attachment.url、photo.attachment.width、photo.attachment.height,对我来说这似乎很一致。您可以选择将附件别名为文件 - 这样您将获得您要求的确切方法名称(photo.file.width,photo.file.url),但我不建议这样做,因为它看起来令人困惑(调用附件“文件”)。

class Photo < ActiveRecord::Base
  def file
    attachment
  end
end

【讨论】:

  • 对 - 问题是,我目前有 photo.file 指向 photo.attachment.file,我想要保留它并指向 photo.attachment.height 和 photo.attachment .width 到 photo.file 以便 photo.file.height(来自 photo.attachment.height)和 photo.file.url(来自 photo.attachment.file.url)都可以工作。
【解决方案4】:

对于普通的 Ruby,你可以使用 Forwardable:

require 'forwardable'

class RecordCollection
  attr_accessor :records
  extend Forwardable
  def_delegator :@records, :[], :record_number
end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多