rails连接表问题

时间:2009-09-18 11:25:18

标签: ruby-on-rails activerecord

我的部分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

3 个答案:

答案 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])
...