如何通过SQL函数使属性设置器发送值

我试图让一个ActiveRecord模型中的属性设置器在rails生成SQL查询之前将其值包装在text2ltree()postgres函数中.

例如,

post.path = "1.2.3"
post.save

应该产生类似的东西

UPDATE posts SET PATH=text2ltree('1.2.3') WHERE id = 123 # or whatever

这样做的最佳方法是什么?

解决方法

编辑:要完全达到您要求的目标,您可以使用它来覆盖模型文件中的认设置器:
def path=(value)
  self[:path] = connection.execute("SELECT text2ltree('#{value}');")[0][0]
end

然后你上面的代码工作.

我有兴趣了解更多关于ActiveRecord的内部结构及其难以理解的元编程基础,所以作为练习,我试图完成你在下面的评论中描述的内容.这是一个适合我的例子(这都是在post.rb中):

module DatabaseTransformation
  extend ActiveSupport::Concern

  module ClassMethods
    def transformed_by_database(transformed_attributes = {})

      transformed_attributes.each do |attr_name,transformation|

        define_method("#{attr_name}=") do |argument|
          transformed_value = connection.execute("SELECT #{transformation}('#{argument}');")[0][0]
          write_attribute(attr_name,transformed_value)
        end
      end
    end
  end
end

class Post < ActiveRecord::Base
  attr_accessible :name,:path,:version
  include DatabaseTransformation
  transformed_by_database :name => "length" 

end

控制台输出

1.9.3p194 :001 > p = Post.new(:name => "foo")
   (0.3ms)  SELECT length('foo');
 => #<Post id: nil,name: 3,path: nil,version: nil,created_at: nil,updated_at: nil>

在现实生活中,我假设您希望将模块包含在ActiveRecord :: Base中,位于加载路径中较早的某个文件中.您还必须正确处理要传递给数据库函数的参数的类型.最后,我了解到,connection.execute由不同的数据库适配器实现的,所以你的方式访问结果可能在Postgres的是不同的(这个例子的sqlite3,在返回结果集作为哈希的阵列和键,将第一数据记录为0].

这篇博文非常有用:

http://www.fakingfantastic.com/2010/09/20/concerning-yourself-with-active-support-concern/

插件创作的Rails指南一样:

http://guides.rubyonrails.org/plugins.html

另外,对于它的价值,我认为在Postgres中我仍然会使用迁移创建一个查询重写规则,但这可以带来很好的学习体验.希望它有效,我现在可以停止思考如何做到这一点.

相关文章

SELECT a.*,b.dp_name,c.pa_name,fm_name=(CASE WHEN a.fm_n...
if not exists(select name from syscolumns where name=&am...
select a.*,pano=a.pa_no,b.pa_name,f.dp_name,e.fw_state_n...
要在 SQL Server 2019 中设置定时自动重启,可以使用 Window...
您收到的错误消息表明数据库 &#39;EastRiver&#39; 的...
首先我需要查询出需要使用SQL Server Profiler跟踪的数据库标...