2

我想知道对一个对象与另一个类的 n 个对象相关联的关系进行建模的最佳方法是什么。我想将 has_one 关系扩展到 n 的特定值。

例如,TopFiveMoviesList 将属于用户并且恰好有五部电影。我会想象底层的 sql 表会有类似 movie_id_1、movie_id_2、...movi​​e_id_5 的字段。

我知道我可以做一个 has_many 关系并限制模型级别的孩子数量,但我宁愿没有中间表。

4

3 回答 3

2

我认为通过连接模型来实现这个模型将是你最好的选择。它允许List模型担心 List 逻辑和Movie模型担心 Movie 逻辑。您可以创建一个Nomination(名称不是最好的,但您知道我的意思)模型来处理电影和列表之间的关系,当限制为 5 时,您可以限制您撤回的提名数量。

有几个原因我认为这种方法更好。

首先,假设您希望能够以两种方式(movie.listslist.movies)遍历关系,那么 5 列方法将变得更加混乱。

While it'd be so much better for ActiveRecord to support has n relationships, it doesn't, and so you'll be fighting the framework on that one. Also, the has n relationship seems a bit brittle to me in this situation. I haven't seen that kind of implementation pulled off in ActiveRecord, though I'd be really interested in seeing it happen. :)

于 2009-01-01T22:03:31.843 回答
1

我假设您的意思是“实施”而不是“模型”?在 UML 中建模非常简单,例如,您有一个由 5 个电影实体组成的 Person 实体。

但是当你说has_one,去has_5时,困难就来了。如果它是一个简单的标量值,has_one 可能是父实体上的一个属性。Has_5 可能是通过 UML 中的“由”关系相互关联的 2 个实体。

要回答的主要问题可能是,“你能保证它永远是‘前五名’吗?” 如果是,请使用列对其进行建模,如您所述。如果不是,则使用另一个实体对其进行建模。

另一个问题可能是,“重构有多容易?” 如果它很简单,见鬼,从 5 列开始,如果它发生变化,重构为单独的实体。

像往常一样,“最佳”取决于业务和技术环境。

于 2008-12-31T15:22:47.923 回答
1

我的第一直觉是使用连接表,但如果这不是可取的,User.movie[1-5]_id列将符合要求。(我认为movie1_id更适合 Rails 约定比movie_id_1。)

由于您标记了此 Rails 和 ActiveRecord,我将在我的答案中添加一些完全未经测试且可能有些错误的模型代码。:)

class User < ActiveRecord::Base
  TOP_N_MOVIES = 5
  (1..TOP_N_MOVIES).each { |n|  belongs_to "movie#{n}".to_sym, :class_name => Movie }
end

您可以将该行包装在宏样式方法中,但除非这是您的应用程序的常见模式,否则这样做可能只会使您的代码更难阅读,而几乎没有 DRY 好处。

您可能还想添加验证以确保用户列表中没有重复的电影。

将您的电影类关联回您的用户是类似的。

class Movie < ActiveRecord::Base

  (1..User::TOP_N_MOVIES).each do |n| 
    has_many "users_list_as_top_#{n}".to_sym, :class_name => User, :foreign_key => "movie#{n}_id"
  end

  def users_list_as_top_anything
    ary = []
    (1..User::TOP_N_MOVIES).each {|n| ary += self.send("users_list_as_top_#{n}") }
    return ary
  end

end

(当然,users_list_as_top_anything写成显式 SQL 可能会更好。我今天很懒。)

于 2008-12-31T23:36:27.567 回答