10

我正在尝试将裁剪图像所需的一些逻辑抽象到模块中,以免弄乱我的模型。代码基于http://railscasts.com/episodes/182-cropping-images

module CroppableImage
  def croppable_image(*image_names)
    image_names.each do |image_name|

      define_method "#{image_name}_sizes" do
        { :cropped => read_attribute("#{image_name}_size").to_s, :large => "800x800>" }
      end

      define_method "#{image_name}_geometry" do |style|
        style ||= :original
        @geometry ||= {}
        @geometry[style] ||= Paperclip::Geometry.from_file(eval "#{image_name}.path(style)")
      end

      define_method "#{image_name}_aspect_ratio" do
        width, height = read_attribute("#{image_name}_size").split("x")
        width.to_f / height.to_f
      end

      private

        define_method "reprocess_#{image_name}" do
          eval "#{image_name}.reprocess!"
        end

    end
  end

end

要将其包含到我的模型中,似乎我必须使用扩展。我认为extend是为了包含类方法。我来自java背景 - 我认为使用扩展基本上在类上创建了静态方法。

class Website < ActiveRecord::Base
  extend CroppableImage
  croppable_image :logo, :footer_image

-- 这行得通

看来我真正想要的是创建实例方法。

class Website < ActiveRecord::Base
  include CroppableImage
  croppable_image :logo, :footer_image

-- 这会抛出错误“undefined method `croppable_image' for #”

谁能解释发生了什么,在这种情况下我是否应该使用包含或扩展。多谢你们

4

2 回答 2

14

extend M内部类似于class << self; include M; end-将extend模块包含到对象的单例类中(并使模块的实例方法成为您扩展的类的单例方法)。

在您的情况下,您croppable_image 在类定义的上下文中调用,因此croppable_image应该是Class类的实例方法或类的单例方法Website

这就是为什么你应该通过使用扩展 CroppableImageWebsite来扩展类的原因——它将实例方法添加为类的单例方法。CroppableImagecroppable_imageWebsite

于 2012-03-15T08:17:11.267 回答
7

您可以同时使用这两种逻辑。Ruby 有扩展和包含的回调 使用包含回调的示例

module CroppableImage
  def self.included(base)
    base.extend(ClassMethods)
  end

  module ClassMethods
    def bar
      puts 'class method'
    end
  end

  def foo
    puts 'instance method'
  end
end
于 2012-03-15T08:32:20.070 回答