如何访问activerecord初始化程序中的当前id序列值?

时间:2014-02-04 18:43:06

标签: ruby-on-rails postgresql activerecord

我正在构建一个activerecord来建模一个会话树,使用数组列类型来表示该树中记录位置的物化路径,使用postgres 9.1,rails 4.0和pg gem。

我真正想做的是在创建新的会话对象时访问currval('conversations_id_seq'),以便我可以将[grandparent_id,parent_id ... current_id]作为数组传递给对象初始化程序。这样我可以指定此列不是null作为数据库约束,并且在无父对话的情况下,它仍然默认为[current_id]。

我遇到的问题是在第一次保存之前访问模型的id值。我总是可以放松not null约束并添加一个after_create钩子,但这感觉很糟糕。我希望有一种方法可以在第一次保存到数据库之前获取在初始化程序中被推入@id的值。

编辑以澄清赏金:在一个理想的世界中,会有一个特殊的标记我可以传递给对象的创建方法:Conversation.create(reply_chain:[:lastval]),其中gem将其视为生成的SQL中的lastval()。

2 个答案:

答案 0 :(得分:4)

类似的东西:

def before_create
   self.id=Conversation.connection.execute("SELECT nextval('conversations_id_seq')")
   self.path = [... , self.id];
   true
end

或使用before insert / update触发器来维护路径。

答案 1 :(得分:0)

如果您不需要数据库中的列,则可以为该属性设置别名。

alias_attribute :current_id, :id

或者您可以在需要时查询ID。

def self.last_val
    ActiveRecord::Base.connection.execute("SELECT lastval('conversations_id_seq')")
end

def self.next_val
    ActiveRecord::Base.connection.execute("SELECT nextval('conversations_id_seq')")
end

Conversation.create(reply_chain: Conversation.next_val)

使用after_save也不是最丑的代码。