我遇到了这个问题:
哪种方式更适合做主旗?
用户
| id | name |
| 1 | Joe |
糖果
| id | user_id | primary |
| 1 | 1 | true |
| 2 | 2 | false |
用户
| id | name | primary_candy_id |
| 1 | Joe | 2 |
糖果
| id | user_id |
| 1 | 1 |
| 2 | 2 |
对Soluion 1的说明
解决方案2的注释
这是更多的SQL问题,但我在项目中使用Rails 3. *所以这个领域的最佳实践意见欢迎
答案 0 :(得分:1)
我会创建一个名为UserCandy
的类型的第三个模型,然后使数据库表看起来像这样:
# users
| id | name |
| 1 | Joe |
# candies
| id | name |
| 1 | foo bar |
# user_candies
| id | user_id | candy_id |
| 1 | 1 | 1 |
# primary_candies
| id | user_candy_id |
| 1 | 1 |
然后我会在用户和糖果之间建立多对多的关系,因为可能有多个人喜欢<insert some special type of candy here>
。
class User < ActiveRecord::Base
has_many :user_candies
has_many :candies, :through => :user_candies
def primary_candy
Candy.primary_for(self).first
end
end
class Candy < ActiveRecord::Base
has_many :user_candies
has_many :users, :through => :user_candies
scope :primary, joins(:user_candies => [:primary_user_candy, :user])
scope :primary_for, lambda {|user| primary.where('users.id' => user.id) }
end
class UserCandy < ActiveRecord::Base
belongs_to :user
belongs_to :candy
has_one :primary_candy
end
class PrimaryCandy < ActiveRecord::Base
belongs_to :user_candy
validate do
if user_candy.user.primary_candy
errors.add(:base, "User already has a primary candy")
end
end
end
这样,当您添加不同类型的小吃时,您不必向users表添加列,而且,由于用户可能有也可能没有喜欢的糖果,您将避免用户中的空字段这样表。
您也可以通过这种方式重复使用不同的糖果类型。
因此,从关系数据库的角度来看,我的简短回答是:我没有旗帜,我会把主要糖果放在一个单独的模型中。
那就是说,你也可以使用三个表版本,只需将主标志放在user_candies表中。
我使用上面的模型代码制作了一个示例rails项目,可用here。
答案 1 :(得分:0)
如何使用has_one关联。这样就可以消除两者中不必要的列,只有在需要时才能轻松访问User.primary_candy。
User :has_many candy
User :has_one candy :through => primary_candy
Candy :belongs_to user
Candy :has_many primary_candy
Primary_candy :belongs_to User
Primary_candy :belongs_to Candy
Primary_candy :validates_uniqueness_of :user_id, :scope => :candy_id
user.primary_candy.candy会返回相关的糖果。 user.candy将返回所有糖果的集合。
您可以在糖果模型中创建一个方法来检查primary_candy和.find也只记录该记录。
def p_candy(user)
p_candy_id = Primary_candy.find_by_user_id(user.id).candy_id
p_candy = Candy.find(p_candy_id)
return p_candy
end
它还使您可以轻松查看不同主要糖果的相对受欢迎程度。 只是,GL。
答案 2 :(得分:0)
在我看来,人们经常通过为不存在的一对多关系创建一个不必要的链接表来使这种情况变得不必要地复杂化。 MyFavoriteColor是“我”(“最喜欢的”)的monadic属性所以我会这样做:
Tables:
PEOPLE
COLORS
和People.FavoriteColor列必须包含COLORS表中的键:
ALTER TABLE PEOPLE ADD CONSTRAINT FK_PEOPLE_COLOR
foreign key(FavoriteColor) REFERENCES COLOR(id)
现在,假设你有一家服装店,你想跟踪一件商品的颜色(红色衬衫,蓝色衬衫,绿色衬衫),为什么你需要一对多的关系联动表:
Tables:
APPAREL
COLORS
APPARELCOLORS
T-Shirt is an item in the APPAREL table
Red, green, blue, white, etc are items in the COLORS table
And then you'd have this in the APPARELCOLORS linkage table:
Apparel | Color
t-shirt | red
t-shirt | blue
hat | white
hat | black
hat | yellow
“最喜欢的”规则 - 也就是说,只有与实体相关的几个值中的一个可以将“最喜欢的”列设置为True--无法强制执行。您应始终寻求一种以声明方式强制执行规则的方法。如果可以的话,你知道你有一个好的设计。