在mixin中引用类属性

时间:2013-10-21 14:43:52

标签: ruby

我是Ruby的新手,我遇到了代码组织问题。

我有一个名为Movie的类,其中包含一个名为IMDBMovieInfo的模块。

class Movie

    include IMDBMovieInfo
    attr_accessor :name
    attr_accessor :year
    attr_accessor :movieID
end

IMDBMovieInfo有一个获取movieID并使用它构建IMDB URL的方法:

module IMDBMovieInfo
    def imdb_url()
        "http://www.imdb.com/title/tt#{self.movieID}/"
    end
end

这里的问题是我不确定我应该引用电影类中的某些内容,因为IMDBMovieInfo不知道该类,不应该。我可以添加一个电影ID的参数,但是如果你不知道Movie对象,你就会这样做,这没有意义:

movie = Movie.new("Titanic", "1997", "0120338")
movie.imdb_url(movie.movieID)

组织此代码的正确方法是什么?

2 个答案:

答案 0 :(得分:2)

如果要在多个类中使用它,您只需要将此代码提取到单独的模块中。然而,我可以重申将大型模型拆分成几个小块的愿望。

例如,您可以建立一个包含类必须遵守的协议,并将其留给id来自的包含类。在以下示例中,包含类必须实现方法imdb_id,该方法应返回将用于url的id:

module IMDBMovieInfo
  def imdb_id
    raise NotImplementedError, 'including class needs to override imdb_id'
  end

  def imdb_url
    "http://www.imdb.com/title/tt#{imdb_id}/"
  end
end

class Movie
  include IMDBMovieInfo

  def imdb_id
    self.movieID
  end

  attr_accessor :name
  attr_accessor :year
  attr_accessor :movieID
end

# In another classs
# (suppose IMDB lists computer games in the future)
class ComputerGame
  include IMDBMovieInfo

  def imdb_id
    self.gameID
  end

  attr_accessor :name
  attr_accessor :year
  attr_accessor :gameID
end
然而,我必须说,我发现整个提取到mixins有点笨拙。另一种方法是创建一个知道如何构建url但不知道id来自哪里的实用程序类:

class IMDBUtil
  def initialize(imdb_id)
    @imdb_id = imdb_id
  end

  def imdb_url
    "http://www.imdb.com/title/tt#{@imdb_id}/"
  end
end

class Movie
  include IMDBMovieInfo

  def imdb_url
    IMDBUtil.new(self.movieId).imdb_url
  end

  attr_accessor :name
  attr_accessor :year
  attr_accessor :movieID
end

为了解决这个问题,这里是great blog post from CodeClimate on how to refactor fat Rails models

答案 1 :(得分:1)

关于你的评论我会说,IMDBMovieInfo模块不应该有一个需要movieID的函数。您可以将它移动到您的Movie类。