我的部分RoR应用程序负责管理网站设计组合。 一个网站设计可以有许多与之相关的图像。 一个图像只能与一个设计相关联。 我使用has_many语句:through参数通过连接表将图像与设计连接起来。并且当删除图像时,必须删除关联表中的条目。所以我有下一个型号 对于图像:
class Image < ActiveRecord::Base
has_one :images_site_designs , :class_name => "ImagesSiteDesigns" , :dependent => :destroy
has_one :site_design , :through => :images_site_designs
end
对于site_designs:
class SiteDesign < ActiveRecord::Base
belongs_to :client
has_many :images_site_designs , :class_name => "ImagesSiteDesigns"
has_many :images , :through => :images_site_designs
end
并加入表images_site_designs:
class ImagesSiteDesigns < ActiveRecord::Base
belongs_to :image
belongs_to :site_design
end
为site_designs创建新图像是可以的,因此下面的代码可以正常工作:
@site_design = SiteDesign.find(params[:id])
@site_design.images << Image.new(params[:image])
但是当我尝试删除图像时,会出现下一个错误:
ActiveRecord::StatementInvalid in ImagesController#destroy
Mysql::Error: Unknown column 'id' in 'where clause': DELETE FROM `images_site_designs` WHERE `id` = NULL
看起来rails使用错误的列名来查询images_site_designs连接表。我该如何解决?
UPD:
删除图像的image_controller函数:
def destroy
@image = Image.find(params[:id])
@image.destroy
respond_to do |format|
format.html { redirect_to(images_url) }
format.xml { head :ok }
end
end
迁移:
class CreateImages < ActiveRecord::Migration
def self.up
create_table :images do |t|
t.string :url
t.string :name
t.text :description
t.timestamps
end
end
def self.down
drop_table :images
end
end
class CreateSiteDesigns < ActiveRecord::Migration
def self.up
create_table :site_designs do |t|
t.string :name
t.text :concept
t.text :description
t.integer :client_id
t.timestamps
end
end
def self.down
drop_table :site_designs
end
end
class CreateImagesSiteDesigns < ActiveRecord::Migration
def self.up
create_table :images_site_designs , :id => false do |t|
t.integer :image_id
t.integer :site_design_id
end
end
def self.down
drop_table :images_site_designs
end
end
答案 0 :(得分:2)
这里的问题是你有一个迁移,它使你的image_site_design不是一个模型(没有id列),但你正在为它创建一个ActiveRecord模型。为了使您正在进行的工作,您需要在连接表中实际拥有一个id列。
答案 1 :(得分:1)
无法真正回答您的问题,因为未显示哪些代码会触发错误。大概是在Image实例上调用destroy,但无法确定。
但是,看起来你不需要那个连接模型。以下似乎满足了这一要求:
class SiteDesign < ActiveRecord::Base
belongs_to :client
has_many :images
end
class Image < ActiveRecord::Base
belongs_to :site_design
end
当然,这需要迁移(drop join table并将site_design_id添加到images表),但似乎是一个更清晰的解决方案。有什么理由不这样做吗?
答案 2 :(得分:0)
如果您希望一个图像只能与一个设计相关联,那么为什么要使用has_and_belongs_to关系(使用n:m表!)
我会重构以下内容:
1)迁移您的Images模型并添加Site_design_id属性
class CreateImages < ActiveRecord::Migration
def self.up
create_table :images do |t|
t.string :url
t.string :name
t.text :description
t.integer :site_design_id
t.timestamps
end
end
def self.down
drop_table :images
end
end
2)删除ImagesSiteDesigns-Migration
drop_table :images_site_designs
3)将模型更改为:
class SiteDesign < ActiveRecord::Base
belongs_to :client
has_many :images
end
class Image < ActiveRecord::Base
belongs_to :site_design
end
所以你最终得到1:n关系,这应该是你的规范的最佳解决方案。
您可以按以下方式访问模型:
Image.first.site_design
=> <SiteDesign #id:...>
SiteDesign.first.image
=> <Image #id...>
SiteDesign.image = Image.new(params[:image])
...