我的公司有一个很久以前用PHP构建的旧网站。我相信数据库模式代表了从未以战略方式考虑过的请求缓慢积累。现在我们抛出PHP代码并使用Rails构建站点。数据库架构仍然保持不变。
我只是围绕Rails,所以这可能是一个简单的问题。
我有一个文章表,数据如下所示:
id: 1102129
article_type_id: 5
old_article_id: 0
title: Zombie Film Locations
subtitle: Hollywood-inspired survival tips for destinations teeming with the undead
display_date: 0000-00-00
author_id: 29
thumbnail_image_id: 12033473
index_image_id: 12033473
article_image_id: 12033473
is_archived: 0
is_featured: 1
is_published: 1
date_to_show: 2011-10-04 00:00:00
off_the_path: 0
created: 2011-10-04 12:45:07
modified: 2011-10-11 15:33:59
fact_check_date: 0000-00-00 00:00:00
unpublish_date: 0000-00-00
is_qsfeatured: 1
featured_order: 0
第二行:
id: 1102128
article_type_id: 14
old_article_id: 0
title: Hotel Adagio [id]35677
subtitle: Hotel Adagio
display_date: 2011-09-29
author_id: 0
thumbnail_image_id: NULL
index_image_id: NULL
article_image_id: NULL
is_archived: 0
is_featured: 0
is_published: 1
date_to_show: 2011-09-29 12:50:38
off_the_path: 0
created: 2011-09-29 12:50:38
modified: 2011-09-29 12:50:38
fact_check_date: NULL
unpublish_date: NULL
is_qsfeatured: 0
featured_order: NULL
图像数据如下:
id: 6722
old_id: 0
type: Index
association_type: TopTen
association_id: 1102129
position: 0
copyright: AMC
caption: The Walking Dead portrays an abandoned, corpse-ridden downtown Atlanta, one of 10 zombie film locations we've scouted out to help you survive (and hide) should the dead rise.
alt_text: Zombie film locations
url: photos/index-TopTens/walkingdeadindex.jpg
_url:
name: index
published: 0
description:
第二行:
id: 6723
old_id: 0
type: Thumbnail
association_type: TopTen
association_id: 1102129
position: 0
copyright: AMC
caption: The Walking Dead portrays an abandoned, corpse-ridden downtown Atlanta, one of 10 zombie film locations we've scouted out to help you survive (and hide) should the dead rise.
alt_text: Zombie film locations
url: photos/thumb-TopTens/walkingdeadthumb.jpg
_url:
name: thumbnail
published: 0
description:
images表中的association_id是文章的id,尽管数据库中没有指定外键。
获得文章后如何获取所有图像?
现在控制器中我做了:
@articles = Article.where(:article_type_id => 5).order("id DESC").limit(5)
在视图中我做了类似的事情:
<%= article.title %>
但是如何从文章模型中引用图像?
为了使这更复杂,图像是多态的,所以我不能简单地创建从图像到文章的外键。图像有时也会映射到“travel_guides”和“slideshows”,这是我们拥有的另外两张表。
更新:
更改了文章,现在它已经:
has_many:images,:foreign_key =&gt; 'association_id'
将我的控制器代码更改为:
@articles = Article.where(:article_type_id => 5).order("id DESC").limit(5).joins(:images)
但在我看来,我这样做:
&lt;%= article.images.url%&gt;
我得到“no method url”错误。
我在做:
&lt;%= article.image.url%&gt;
在图像上没有“s”,然后我得到“没有方法'图像'”。
更新:
所以,好吧,在命令行中,我运行“rails c”进入控制台,然后运行我在控制器中使用的代码:
@articles = Article.where(:article_type_id =&gt; 5).order(“id DESC”)。limit(5).joins(:image)
这给了我:
@articles = Article.where(:article_type_id => 5).order("id DESC").limit(5).joins(:image)
Article Load (11.5ms) SELECT `articles`.* FROM `articles` INNER JOIN `images` ON `images`.`association_id` = `articles`.`id` WHERE `articles`.`article_type_id` = 5 ORDER BY id DESC LIMIT 5
=> [#<Article id: 1102129, article_type_id: 5, old_article_id: 0, title: "Zombie Film Locations", subtitle: "Hollywood-inspired survival tips for destinations t...", display_date: nil, author_id: 29, thumbnail_image_id: 12033473, index_image_id: 12033473, article_image_id: 12033473, is_archived: false, is_featured: true, is_published: true, date_to_show: "2011-10-04 00:00:00", off_the_path: false, created: "2011-10-04 12:45:07", modified: "2011-10-18 10:44:15", fact_check_date: nil, unpublish_date: nil, is_qsfeatured: true, featured_order: 1, slug: "zombie-film-locations">, #<Article id: 1102129, article_type_id: 5, old_article_id: 0, title: "Zombie Film Locations", subtitle: "Hollywood-inspired survival tips for destinations t...", display_date: nil, author_id: 29, thumbnail_image_id: 12033473, index_image_id: 12033473, article_image_id: 12033473, is_archived: false, is_featured: true, is_published: true, date_to_show: "2011-10-04 00:00:00", off_the_path: false, created: "2011-10-04 12:45:07", modified: "2011-10-18 10:44:15", fact_check_date: nil, unpublish_date: nil, is_qsfeatured: true, featured_order: 1, slug: "zombie-film-locations">, #<Article id: 1102129, article_type_id: 5, old_article_id: 0, title: "Zombie Film Locations", subtitle: "Hollywood-inspired survival tips for destinations t...", display_date: nil, author_id: 29, thumbnail_image_id: 12033473, index_image_id: 12033473, article_image_id: 12033473, is_archived: false, is_featured: true, is_published: true, date_to_show: "2011-10-04 00:00:00", off_the_path: false, created: "2011-10-04 12:45:07", modified: "2011-10-18 10:44:15", fact_check_date: nil, unpublish_date: nil, is_qsfeatured: true, featured_order: 1, slug: "zombie-film-locations">, #<Article id: 1102122, article_type_id: 5, old_article_id: 0, title: "Nude Vacations", subtitle: "These places to get naked around the world make for...", display_date: nil, author_id: 574, thumbnail_image_id: 12024629, index_image_id: 12024629, article_image_id: 12024629, is_archived: false, is_featured: true, is_published: true, date_to_show: "2011-09-23 00:00:00", off_the_path: false, created: "2011-09-23 13:13:41", modified: "2011-10-18 10:44:15", fact_check_date: nil, unpublish_date: nil, is_qsfeatured: true, featured_order: 2, slug: "nude-vacations">, #<Article id: 1102122, article_type_id: 5, old_article_id: 0, title: "Nude Vacations", subtitle: "These places to get naked around the world make for...", display_date: nil, author_id: 574, thumbnail_image_id: 12024629, index_image_id: 12024629, article_image_id: 12024629, is_archived: false, is_featured: true, is_published: true, date_to_show: "2011-09-23 00:00:00", off_the_path: false, created: "2011-09-23 13:13:41", modified: "2011-10-18 10:44:15", fact_check_date: nil, unpublish_date: nil, is_qsfeatured: true, featured_order: 2, slug: "nude-vacations">]
因此,尽管有联接,但没有任何图像数据显示出来。
更新:
嗯,现在我看到我在轨道控制台上的那个块,我看到每篇文章都返回了3次,我假设因为JOIN:
文章编号:1102129,article_type_id:5,old_article_id:0,标题:“Zombie Film Locations”,副标题:“好莱坞风格的目的地生存技巧...”,display_date:nil,author_id:29,thumbnail_image_id: 12033473,index_image_id:12033473,article_image_id:12033473,is_archived:false,is_featured:true,is_published:true,date_to_show:“2011-10-04 00:00:00”,off_the_path:false,created:“2011-10-04 12 :45:07“,修改:”2011-10-18 10:44:15“,fact_check_date:nil,unpublish_date:nil,is_qsfeatured:true,featured_order:1,slug:”zombie-film-locations“&gt;,< / p>
所以我得到3篇文章,因为3个与图像的关联,但我没有得到图像。这是两个世界中最糟糕的。
真的,对图像进行单独查询会更容易。
更新:
这个SQL给了我想要的东西,但我似乎无法将其变成Rails查询:
SELECT articles.title, articles.subtitle, images.url, images.caption
FROM articles
JOIN images ON articles.id = images.association_id
WHERE images.type='Thumbnail'
ORDER BY articles.id desc
LIMIT 5 \G
更新:
我无法让它发挥作用。我认为Ruby导师会教我一些基本的Ruby和Rails东西。我很乐意付钱。我在这里发布我的问题:http://tutorruby.com/question/show?id=3235
答案 0 :(得分:1)
要访问文章中的图像,您需要在Article类中添加关联:
class Article
has_many :images, :foreign_key => :association_id
end
您提到有时图像会映射到travel_guides和幻灯片(另外两张表)。您必须为每个表添加关联。所以你可以这样做:
class Article < ActiveRecord::Base
has_many :images, :foreign_key => :association_id
has_many :travel_guides, :foreign_key => :association_id
has_many :slideshow_images, :foreign_key => :association_id
end
建立反向关联通常也是一个好主意:
class Image < ActiveRecord::Base
belongs_to :article, :foreign_key => :association_id
end
class TravelGuide < ActiveRecord::Base
belongs_to :article, :foreign_key => :association_id
end
class SlideshowImage < ActiveRecord::Base
set_table_name :slideshows
belongs_to :article, :foreign_key => :association_id
end
需要考虑的一些事项:
我在* has_many *关联中省略了:dependent选项。这通常不是一个好主意。您可以设置:depedent =&gt; :destroy ,以便您可以在图像类中调用一些清理逻辑(删除图像文件)。
如果您没有简单连接,则应考虑将:conditions 选项添加到has_many(或属于)。
如果上述建议无法解决您的所有问题,则可以使用单表继承和/或多态关联。
答案 1 :(得分:1)
在图像关联中指定“has_many”时,表示文章包含图像集合,因此article.images返回一个数组。数组上没有定义'url'方法。要访问url方法,您需要访问每个单独的数组成员,并调用该对象上的url。类似的东西:
article.images[0].url
或
article.images.first.url
答案 2 :(得分:0)
您需要在模型中指定关联。有一个像你一样的namin惯例,但你的表并没有遵循,但这根本不是问题。有两种可能的解决方案。
1。)你重命名数据库中的列(当应用程序仍在使用PHP生产时,什么不会工作)
2.。)使用:foreign_key参数指定关联,如下所示:
文章:
has_many :images, :foreign_key => 'association_id'
照片:
belongs_to :article, :foreign_key => 'association_id'
但是你需要参加一些事情。您将在命名表格图像时遇到一些问题,因为它们还有一个公共文件夹“images”,当您调用以数字开头的图片时,rails将其解释为id并尝试从数据库中获取Image实例而不是传送图像。
Secound问题可能会导致一个名为“association_type”的字段,它会暗示这些字段是多态关联。当你切换到rails时,你也可以重命名。
答案 3 :(得分:0)
articles = Article.includes(:images).where(:article_type_id => 5, :images => { :image_type => 'Thumbnail' }).order('articles.id DESC').limit(5) #no database query is fired yet by rails
article = articles.first # Here we fire the first query, and this query also fetches the image of the article
article.images.first #again fires no query but returns the first image of the article
还有另一种情况,您应该触发数据库查询以从数据库中仅获取一个图像。 那你应该做点什么,
articles = Article.where(:article_type_id => 5).order("id DESC").limit(5) #again fires no db query
article = articles.first #fires db query to get first article
image = article.images.first #fires query for only first image of the article
如果每篇文章的图像数量较少,则第一种方法是有效的,但如果每篇文章有大量图像,则第二种方法是有效的
现在你的rails查询上面发布的sql,
SELECT articles.title, articles.subtitle, images.url, images.caption
FROM articles
JOIN images ON articles.id = images.association_id
WHERE images.type='Thumbnail'
ORDER BY articles.id desc
LIMIT 5
articles = Article.joins(:images).select("articles.title, articles.subtitle, images.url, images.caption").where("images.type = 'Thumbnail'").order("articles.id DESC").limit(5)
article = articles.first
first_image = article.images.first