0

我正在编写我的第一个 RoR 应用程序,目前我正在努力允许用户上传图像。我为此目的使用回形针。其中一个步骤涉及添加has_attached_file到我的模型中:

class MyModel < ActiveRecord::Base
  #...
  has_attached_file :picture, styles: {
    large: "120x150#>", 
    small: "60x75#>"
  }
  #...
end

如果我这样做,一切都会顺利进行(或者看起来如此)。但我还需要在其他地方访问与整数相同的常量值,所以我添加了一个哈希:

class MyModel < ActiveRecord::Base
  #...
  has_attached_file :picture, styles: {
    large: "120x150#>", 
    small: "60x75#>"
  }
  def picture_sizes
  {
    large: {width: 120, height: 150},
    small: {width: 60, height: 75}
  }
  end
  #...
end

这造成了丑陋的冗余。所以我想写一个从第二个哈希生成第一个哈希的方法,像这样

class MyModel < ActiveRecord::Base
  #...
  has_attached_file :picture, styles: picture_sizes_as_strings

  def picture_sizes
  {
    large: {width: 120, height: 150},
    small: {width: 60, height: 75}
  }
  end

  def picture_sizes_as_strings
    result = {}
    picture_sizes.each do |label, size|
      result[:label] = "#{size[:width]}x#{size[:height]}#>"
    end
    return result
  end
  #...
end

但这会引发一个错误:

undefined local variable or method `picture_sizes_as_strings' for #<Class:0x007fdf504d3870>

我究竟做错了什么?

4

2 回答 2

1

问题是您试图在声明 ( ) 中使用实例方法picture_sizes_as_strings,该声明 ( has_attached_image) 在类级别上运行。这就是打电话的区别

MyModel.picture_sizes_as_strings

MyModel.first.picture_sizes_as_strings

在第一种情况下,我们指的是类方法(类 MyModel 本身的方法),在第二种情况下,我们指的是实例方法(单个 my_model 对象上的方法。)

因此,首先您必须通过在名称前加上前缀来将方法更改为类方法self.,因此:

def self.picture_sizes
  {
    large: {width: 120, height: 150},
    small: {width: 60, height: 75}
  }
end

现在这还不能完全解决您的问题,因为has_attached_image在模型第一次由 ruby​​ 解析时处理。has_attached_image这意味着它会在你定义之前尝试运行,self.picture_sizes所以它仍然会说undefined method.

self.picture_sizes您可以通过在声明之前添加来解决此问题,has_attached_file但这很丑陋。您也可以将数据放在一个常量中,但这有其自身的问题。

老实说,没有真正漂亮的方法来解决这个问题。如果是我,我可能会颠倒整个过程,将样式定义为正常,然后使用一种方法将字符串转换为整数,如下所示:

class MyModel < ActiveRecord::Base
  has_attached_file :picture, styles: {
    large: "120x150#>", 
    small: "60x75#>"
  }

  def numeric_sizes style
    # First find the requested style from Paperclip::Attachment
    style = self.picture.styles.detect { |s| s.first == style.to_sym }

    # You can consolidate the following into one line, I will split them for ease of reading
    # First strip all superfluous characters, we just need the numerics and the 'x' to split them
    sizes = style.geometry.gsub(/[^0-9x]/,'')
    # Next split the two numbers across the 'x'
    sizes = sizes.split('x')
    # Finally convert them to actual integer numbers
    sizes = sizes.map(&:to_i)
  end
end

然后,您可以调用MyModel.first.numeric_sizes(:medium)以找出特定样式的大小,以数组形式返回。当然,您也可以将它们更改为哈希或您需要的任何格式。

于 2012-08-26T19:26:42.123 回答
1

has_attached_file运行时评估。您已经定义了一个实例方法,但您没有从实例上下文中调用该方法。

尝试:

def self.picture_sizes_as_strings
  # code here
end

self.确保您还定义了另一种方法

接着:

has_attached_file :picture, :styles => picture_sizes_as_strings

应该管用。

于 2012-08-26T19:12:06.503 回答