我正在使用Rails和PostgreSQL并且正在进行基本的一对多关系,一个Auction
有很多Bid
个。但是,当我尝试删除拍卖(有出价)时,我收到以下错误:
错误:表格上的更新或删除“拍卖”违反了外键 表“出价”上的约束“fk_rails_43e9021cbf”。细节:钥匙(id)=(1) 仍然从表格“出价”中引用。
删除没有出价的拍卖会没有错误。
困扰我的部分是我的Auction
模型中,我有:
has_many :bids, dependent: :destroy
由于我有一个依赖的destroy子句,为什么我仍然会收到此错误?
编辑:我尝试删除整个数据库,然后重新创建/重新迁移所有内容 - 仍然会遇到相同的错误。
答案 0 :(得分:34)
从 Rails v4.2 ,你可以这样做:
创建迁移以更新外键
<强> 20160321165946_update_foreign_key.rb
强>
class UpdateForeignKey < ActiveRecord::Migration
def change
# remove the old foreign_key
remove_foreign_key :posts, :users
# add the new foreign_key
add_foreign_key :posts, :users, on_delete: :cascade
end
end
答案 1 :(得分:16)
您使用delete
或destroy
删除对象吗?我认为您使用的是delete
,并且您想使用destroy
答案 2 :(得分:12)
我的问题是我在尝试删除记录时使用@ auction.delete(在我发布的屏幕截图中可见)。
删除将忽略我所拥有的任何回调。所以即使我有一个依赖的destroy子句,它也没有被调用 - 因此Rails会抛出一个错误。如果/当我将代码更改为@ auction.destroy时,调用了回调并解决了问题。
答案 3 :(得分:8)
您是否偶然使用paranoia宝石或类似的东西?
如果您bids
paranoid
且auctions
不是dependent: destroy
,则可能会遇到此错误。
这会发生,因为当rails执行deleted_at
时,它会软删除出价,但它们实际上仍存在于数据库中(它们只设置了public static Result myprofile() {
DynamicForm requestData = Form.form().bindFromRequest();
Integer id = Integer.parseInt(requestData.get("id"));
try {
JSONObject jo = null;
Connection conn = DB.getConnection();
ResultSet rs;
JSONArray ja = new JSONArray();
PreparedStatement ps = conn.prepareStatement("SELECT p.fullname as fullname, s.post as post,to_char(s.created_on, 'MON DD,YYYY') as created_on,s.last_reply as last_reply,s.id as id,s.comments as comments,s.state as state,s.city as city,s.id as id FROM profiles as p INNER JOIN streams as s ON (s.profile_id=p.id) WHERE s.profile_id=? order by created_on desc");
ps.setInt(1, id);
rs = ps.executeQuery();
while (rs.next()) {
jo = new JSONObject();
jo.put("fullname", rs.getString("fullname"));
jo.put("post", rs.getString("post"));
jo.put("city", rs.getString("city"));
jo.put("state", rs.getString("state"));
jo.put("comments", rs.getInt("comments"));
jo.put("id", rs.getInt("id"));
jo.put("last_reply", difference(rs.getInt("last_reply"), rs.getString("created_on")));
ja.put(jo);
}
JSONObject mainObj = new JSONObject();
mainObj.put("myprofile", ja);
String total = mainObj.toString();
System.err.println(total);
conn.close();
return ok(total);
} catch (Exception e) {
e.getMessage();
}
return ok();
}
列)。因此,外键约束将失败。
答案 4 :(得分:4)
您的错误来自数据库而不是rails。您需要先在应用中删除出价,或更改数据库中的外键约束以级联删除
答案 5 :(得分:1)
MarcBusquéa very good article对此问题有所帮助。
“当ActiveRecord遇到外键违规时,它会引发一个ActiveRecord :: InvalidForeignKey异常。即使在其文档中它只是说当一条记录无法插入或更新时引发它,因为它引用了一条不存在的记录,事实是它也用于我们感兴趣的情况。“
有了这个和rescue_from,我们可以添加到ApplicationController或控制器关注:
rescue_from 'ActiveRecord::InvalidForeignKey' do
# Flash and render, render API json error... whatever
end
答案 6 :(得分:0)
其他答案也不错,但是请不要提及有时您要保留从属记录,而使外键无效。
class Post < ActiveRecord::Base
has_many :comments, dependent: :nullify
end
请注意,这将需要确保数据库表中的外键列为空:true
我不是很肯定,但是您可能还需要在依赖模型中定义的归属关联中添加 可选:true 。
答案 7 :(得分:0)
一个非常简单的解释:关联的表至少包含1条记录,这些记录已连接到您要销毁的表中的记录。
要解决此问题,请添加dependent: :destroy
(假设用户有has_many个帖子)
has_many :post, dependent: :destroy