【问题标题】:Can I write PostgreSQL functions on Ruby on Rails?我可以在 Ruby on Rails 上编写 PostgreSQL 函数吗?
【发布时间】:2015-11-04 08:54:08
【问题描述】:

我们正在启动一个基于 Ruby on Rails 的项目。我们曾经使用 Perl 和 PostgreSQL 函数,以及 Rails 和 Active Record 我还没有看到我们应该如何在 PostgreSQL 中创建函数并使用 Active Record 和模型保存记录。

我知道我们可以在 PostgreSQL 中手动创建它,但 Active Record 的“魔力”在于可以使用所有模型重新创建数据库。

有什么方法可以使用 Rails 创建 PostgreSQL 函数并将其保存在模型中?

【问题讨论】:

  • AFAIK 没有通过 Rails 编写 SQL 函数的内置方法,但根据函数的不同,将它们重构为 scopes 或其他模型方法可能会更好。
  • 但是,您可以简单地在定义 SQL 函数的 lib 目录中编写一个类。你可以通过ActiveRecord::Base.connection.execute执行任意SQL。
  • 您在寻找某种支持 ActiveRecord 的“PL/Ruby”吗?

标签: ruby-on-rails ruby postgresql function rails-activerecord


【解决方案1】:

如果您的唯一要求是在 Rails 应用程序的某个位置创建它们,则可以通过 ActiveRecord::Base.connection.execute 来实现,您可以使用它来执行原始 SQL 查询。

stmt = 'CREATE FUNCTION...'
ActiveRecord::Base.connection.execute stmt

然后您也可以使用 ActiveRecord::Base.connection.execute 调用该函数(我想您的模型中会有方法来处理这个问题)。

【讨论】:

    【解决方案2】:

    这部分问题:

    我知道我们可以在 PostgreSQL 中手动创建它,但 Active Record 的“魔力”在于可以使用所有模型重新创建数据库。

    告诉我,您确实在寻找一种将 PostgreSQL 函数与常规 Rails 迁移过程和 Rake 任务(例如 db:schema:load)集成的方法。

    在迁移中添加和删除函数很容易:

    def up
      connection.execute(%q(
        create or replace function ...
      ))
    end
    
    def down
      connection.execute(%q(
        drop function ...
      ))
    end
    

    您需要使用单独的 updown 方法而不是单个 change 方法,因为 ActiveRecord 将不知道如何应用,更不用说反转函数创建了。您使用connection.execute 将原始函数定义提供给 PostgreSQL。您也可以在change 中使用reversible 来执行此操作:

    def change
      reversible do |dir|
        dir.up do
          connection.execute(%q(
            create or replace function ...
          ))
        end
        dir.down do
          connection.execute(%q(
            drop function ...
          ))
        end
      end
    end
    

    但我发现它比 updown 更吵。

    但是,schema.rb 和与schema.rb 一起使用的常用 Rake 任务(例如 db:schema:loaddb:schema:dump)将不知道如何处理 PostgreSQL 函数以及 ActiveRecord 无法理解的其他事情。不过有一种解决方法,您可以通过设置选择使用structure.sql 文件而不是schema.rb

    config.active_record.schema_format = :sql
    

    在您的config/application.rb 文件中。之后,db:migrate 将写入一个db/structure.sql 文件(这只是您的 PostgreSQL 数据库的原始 SQL 转储,没有您的数据)而不是db/schema.rb。您还将使用不同的 Rake 任务来处理 structure.sql

    • db:structure:dump 而不是 db:schema:dump
    • db:structure:load 而不是 db:schema:load

    其他一切都应该一样。

    这种方法还允许您在数据库中使用 ActiveRecord 无法理解的其他内容:检查约束、触发器、非简单的列默认值,...

    【讨论】:

    • 另一种选择:F(x) 向 ActiveRecord::Migration 添加方法以在 Rails 中创建和管理数据库函数和触发器。 F(x) gem
    猜你喜欢
    • 1970-01-01
    • 2021-11-23
    • 1970-01-01
    • 2014-10-08
    • 2018-11-10
    • 1970-01-01
    • 2016-04-11
    • 1970-01-01
    • 2013-01-07
    相关资源
    最近更新 更多