我有一对rails(4)模型,议程和 agenda_items ,以便议程 has_many agenda_items 和 agenda_item belongs_to 议程。很直接。
agenda_item 有两列: position (索引)和 description 。
我需要交换两个 agenda_items ,所以我交换了两个位置(在 agenda_item 模型中)并保存!这两个记录。当我检查两条记录时,位置已相应更新。
交换后(仍然在模型中)我立即记录议程。 agenda_items ,但发现更改不 。 agenda_items 的部分呈现也不会改变。
当我刷新页面时,我发现更改已发生。我曾尝试将交易所交易(无济于事)。我在交换和日志记录之间破解了一个睡眠声明。交换后(但在睡眠期间),我可以看到它已在pgAdmin III中正确完成。
我尝试了Agenda(Item).connection.commit_db_transaction
,但两个都向我发出警告,说明没有任何交易处于活动状态。
我在postgresql和sqlite3中尝试了这个,两者都表现出相同的症状。
类似的代码在Rails 2中有效,但直到现在我还没有在3或4中使用它。
非常感谢任何想法/建议。
模型代码(还有很多黑客)是:
def exchange( up )
delta = up ? -1 : 1
for item in self.agenda.agenda_items
Zlogger.debug "before exchange: item #{item.position}: #{item.description}"
end
Zlogger.debug "delta: #{delta}"
target = self.agenda.agenda_items.where(['position = ?',self.position + delta]).first
Zlogger.debug "exchanging #{self.position} #{self.description} #{target.position} #{target.description}"
p = self.position
# moving the target to position 0, later moving it to its destination
# is a hack to make sure that the moves are committed immediately (doesn't always work)
ActiveRecord::Base.transaction do
target.position = 0
target.save!
self.position = self.position + delta
self.save!
target.position = p
target.save!
self.agenda.save!
end
Zlogger.debug "exchanged #{self.position} #{self.description} #{target.position} #{target.description}"
sleep 30.0
for item in self.agenda.agenda_items
Zlogger.debug "after exchange: item #{item.position}: #{item.description}"
end
end
Zlogger的典型结果:
before exchange: item 1: Treasurer''s Report
before exchange: item 2: Approval of Last Month''s Minutes
before exchange: item 3: Permanent Layout Report
before exchange: item 4: Sectional Layout Report
before exchange: item 5: HO Layout Report
before exchange: item 6: Operating Committee Report
before exchange: item 7: Membership Promotion and Engagement
before exchange: item 8: New Business
before exchange: item 9: Adjournment
delta: 1
*** Note that the exchange does take place ***
exchanging 1 Treasurer''s Report 2 Approval of Last Month''s Minutes
exchanged 2 Treasurer''s Report 1 Approval of Last Month''s Minutes
*** Note that the exchange has not propagated to the association ***
after exchange: item 1: Treasurer''s Report
after exchange: item 2: Approval of Last Month''s Minutes
after exchange: item 3: Permanent Layout Report
after exchange: item 4: Sectional Layout Report
after exchange: item 5: HO Layout Report
after exchange: item 6: Operating Committee Report
after exchange: item 7: Membership Promotion and Engagement
after exchange: item 8: New Business
after exchange: item 9: Adjournment
答案 0 :(得分:0)
我修好了!我一直在挖掘,经过长时间的谷歌会议后,我发现rails会缓存一个活跃的记录关联。当我更改相关项的内容时,我会认为缓存将无效,因此下一次引用该关联将获得新值,但它不是。
有两种方法可用于解决此问题:
reset
- >如果关联已更改,则重新加载关联。 根据rails文档,这是首选方法 - 但它不起作用!
或
reload
- >即使不需要重新加载,也会强制关联重新加载。 这有效!
就我而言,由于已知前面的语句已经更改了关联的内容,因此保证需要reload
,因此reset
有点多余。
在删除所有调试和黑客之后,代码很简单:
def exchange( up )
delta = up ? -1 : 1
target = self.agenda.agenda_items.where(['position = ?',self.position + delta]).first
target.position = self.position
self.position = self.position + delta
target.save!
self.save!
self.agenda.agenda_items.reload # makes agenda_items consistent with updated contents.
end
我不知道这是否是rails中的错误,但正如我在我的问题中所说,我在Rails 2中使用了类似的代码 - 但不需要reset
或reload
IIRC。 rails文档还暗示reset
应检测到内容已被修改的事实,并仅在需要时调用reload
。