Ruby on rails _和_属于_和_许多可能通过解决方案

Ruby on rails _和_属于_和_许多可能通过解决方案,ruby-on-rails,has-and-belongs-to-many,Ruby On Rails,Has And Belongs To Many,在过去的几个小时里,我一直在为这个问题头疼,我似乎无法理解自己。好的,我有两个像这样的模型 class Book < ActiveRecord::Base has_and_belongs_to_many :categories end class Category < ActiveRecord::Base has_and_belongs_to_many :books end 您应该将模式更改为使用has_many:through-这将允许您将数据放入联接模型中 型号: c

在过去的几个小时里,我一直在为这个问题头疼,我似乎无法理解自己。好的,我有两个像这样的模型

class Book < ActiveRecord::Base
  has_and_belongs_to_many :categories
end

class Category < ActiveRecord::Base
  has_and_belongs_to_many :books
end

您应该将模式更改为使用has_many:through-这将允许您将数据放入联接模型中

型号:

class Book < ActiveRecord::Base
  has_many :book_categories, :dependent => :destroy
  has_many :categories, :through => :book_categories
end

class Category < ActiveRecord::Base
  has_many :book_categories, :dependent => :destroy
  has_many :books, :through => :book_categories
end

class BookCategory < ActiveRecord::Base
  belongs_to :book
  belongs_to :category
end 
这里发生的事情是rails将通过books\u categories自动执行从类别到书籍的连接,我们正在对连接表应用一个条件

剩下的就是确保只有一本书对给定的类别是最好的。我会在BookCategory中使用after_save方法来实现这一点:

class BookCategory < ActiveRecord::Base
  after_save :ensure_only_one_best_per_category

  def ensure_only_one_best_per_category
    if self.best
      BookCategory.all(:conditions => ["category_id = ? and best =  ? id <> ?", self.category_id, true, self.id]).each{|bc| bc.update_attributes(:best => false)} 
    end
  end
class BookCategory[“category_id=?and best=?id?”,self.category_id,true,self.id])。每个{bc | bc.update_属性(:best=>false)}
结束
结束

如果您希望对不同类别的书籍进行评级,而不是简单地说它们是否是“最佳”的话,这个系统很容易扩展:在这种情况下,您可以将
best
布尔字段替换为
rating
float字段或其他内容。

Thx dude,你们可能刚刚救了我一命,让我免于无数次撞墙的痛苦
class Book < ActiveRecord::Base
  has_many :book_categories, :dependent => :destroy
  has_many :categories, :through => :book_categories
end

class Category < ActiveRecord::Base
  has_many :book_categories, :dependent => :destroy
  has_many :books, :through => :book_categories
end

class BookCategory < ActiveRecord::Base
  belongs_to :book
  belongs_to :category
end 
#in Category
def best_book
  self.books.first(:conditions => ["books_categories.best = ?", true]
end
class BookCategory < ActiveRecord::Base
  after_save :ensure_only_one_best_per_category

  def ensure_only_one_best_per_category
    if self.best
      BookCategory.all(:conditions => ["category_id = ? and best =  ? id <> ?", self.category_id, true, self.id]).each{|bc| bc.update_attributes(:best => false)} 
    end
  end