0

我对 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)

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

4

2 回答 2

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

总结一下,这里有一篇来自 CodeClimate 的关于如何重构胖 Rails 模型的精彩博客文章

于 2013-10-21T15:09:29.097 回答
1

关于您的评论,我想说,IMDBMovieInfo 模块不应该有需要movieID 的功能。你可以把它移到你的电影类。

于 2013-10-21T15:07:39.160 回答