Rails HABTM 加入另一个条件

发布于 2024-11-19 01:59:28 字数 1365 浏览 3 评论 0原文

我正在尝试获取一个列表,我将以书籍为例。

class Book < ActiveRecord::Base
  belongs_to  :type
  has_and_belongs_to_many   :genres
end

class Genre < ActiveRecord::Base
  has_and_belongs_to_many   :books
end

因此,在这个示例中,我想显示所有流派的列表,但第一列应该是类型。因此,如果说流派是“Space”,则类型可以是“Non-fiction”和“Fiction”,并且它将显示:

Type          Genre    
Fiction       Space
Non-fiction   Space

流派表只有“id”、“name”和“description”,连接表genredes_books有“genre_id”和“book_id”,Book表有“type_id”和“id”。然而,我很难让它发挥作用。

我知道我需要的 sql 代码是:

SELECT distinct genres.name, books.type_id FROM `genres` INNER JOIN genres_books ON genres.id = genres_books.genre_id INNER JOIN books ON genres_books.book_id = books.id order by genres.name

我发现我可以这样做

@genre = Genre.all
@genre.each do |genre|
  @type = genre.book.find(:all, :select => 'type_id', :group => 'type_id')
  @type.each do |type|

,这可以让我看到每种类型的类型并将它们打印出来,但我无法真正同时使用它们。我认为最理想的情况是,在 Genre.all 声明中,我可以以某种方式将它们分组,这样我就可以将流派/类型组合在一起,并在以后与它们一起工作。我试图做一些类似的事情:

 @genres = Genre.find(:all, :include => :books, :select => 'DISTINCT genres.name, genres.description, books.product_id', :conditions => [Genre.book_id = :books.id, Book.genres.id = :genres.id] )

但此时我正在原地踏步,却一无所获。我需要使用 has_many :through 吗?

I am trying to get a list, and I will use books as an example.

class Book < ActiveRecord::Base
  belongs_to  :type
  has_and_belongs_to_many   :genres
end

class Genre < ActiveRecord::Base
  has_and_belongs_to_many   :books
end

So in this example I want to show a list of all Genres, but it the first column should be the type. So, if say a genre is "Space", the types could be "Non-fiction" and "Fiction", and it would show:

Type          Genre    
Fiction       Space
Non-fiction   Space

The Genre table has only "id", "name", and "description", the join table genres_books has "genre_id" and "book_id", and the Book table has "type_id" and "id". I am having trouble getting this to work however.

I know the sql code I would need which would be:

SELECT distinct genres.name, books.type_id FROM `genres` INNER JOIN genres_books ON genres.id = genres_books.genre_id INNER JOIN books ON genres_books.book_id = books.id order by genres.name

and I found I could do

@genre = Genre.all
@genre.each do |genre|
  @type = genre.book.find(:all, :select => 'type_id', :group => 'type_id')
  @type.each do |type|

and this would let me see the type along with each genre and print them out, but I couldn't really work with them all at once. I think what would be ideal is if at the Genre.all statement I could somehow group them there so I can keep the genre/type combinations together and work with them further down the road. I was trying to do something along the lines of:

 @genres = Genre.find(:all, :include => :books, :select => 'DISTINCT genres.name, genres.description, books.product_id', :conditions => [Genre.book_id = :books.id, Book.genres.id = :genres.id] )

But at this point I am running around in circles and not getting anywhere. Do I need to be using has_many :through?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

习ぎ惯性依靠 2024-11-26 01:59:28

以下示例使用上面定义的模型。您应该使用范围将关联推回到模型中(或者您可以只在模型上定义类方法)。这有助于控制您的记录获取呼叫,并帮助您遵守德米特定律。

获取书籍列表,无条件地急切地加载每本书的类型和流派:

def Book < ActiveRecord::Base
  scope :with_types_and_genres, include(:type, :genres)
end

@books = Book.with_types_and_genres  #=> [ * a bunch of book objects * ]

一旦你有了这个列表,如果我理解你的目标,你可以做一些 in-Ruby 分组,将你的书籍纳入你需要传递到的结构中你的观点。

@books_by_type = @books.group_by { |book| book.type }

# or the same line, more concisely
@books_by_type = @books.group_by &:type

@books_by_type.each_pair do |type, book|
  puts "#{book.genre.name} by #{book.author} (#{type.name})"
end

The following examples use your models, defined above. You should use scopes to push associations back into the model (alternately you can just define class methods on the model). This helps keep your record-fetching calls in check and helps you stick within the Law of Demeter.

Get a list of Books, eagerly loading each book's Type and Genres, without conditions:

def Book < ActiveRecord::Base
  scope :with_types_and_genres, include(:type, :genres)
end

@books = Book.with_types_and_genres  #=> [ * a bunch of book objects * ]

Once you have that, if I understand your goal, you can just do some in-Ruby grouping to corral your Books into the structure that you need to pass to your view.

@books_by_type = @books.group_by { |book| book.type }

# or the same line, more concisely
@books_by_type = @books.group_by &:type

@books_by_type.each_pair do |type, book|
  puts "#{book.genre.name} by #{book.author} (#{type.name})"
end
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文