估计很多人看到标题都不知道是什么意思
。我也实在想不到比较清晰的标题……
当Rails和PostgreSQL碰到一起时,schema的意思就变得非常模糊了。对Rails而言,schema就是数据库的结构,实际上对大多数的数据库而言也是这样。而PostgreSQL中的schema指的是数据库和数据库对象(表,序列等)中间的一层,我也不知道翻译过来该叫什么,但pgAdmin中把这东西叫“模式”。用过PostgreSQL的同学应该不会陌生。下面的内容中,我会统一地把PostgreSQL中的schema叫做“模式”。
这篇文章,说的就是如何写这么一个迁移文件 -- 在指定的模式中进行操作,如创建表。比如以下代码的作用,就是在project模式下创建users表。
# config/initializers/migration_ext.rb
class CreateProjectTables < ActiveRecord::Migration
def self.up
run_in_schema :project do
create_table :users do |t|
t.string :login
end
end
end
end
这段代码和普通的migration文件没有什么区别,只是在create_table的外层加了一个run_in_schema而已。这样,users表就不是创建在默认的public模式,而是project模式。
run_in_schema在这里做了两件事:
- 如果数据库中没有project模式,则创建project模式。
- 让block中执行的所有操作(建表,执行指定sql语句等)都只影响project模式(这不是绝对的,下面会说明)。
run_in_schema的代码如下:
class ActiveRecord::Migration
def self.run_in_schema(schema, &block)
schema = schema.to_s
# 如果没有该schema,就创建一个
schemas = select_values "SELECT * FROM pg_catalog.pg_namespace WHERE nspname <> 'information_schema' AND nspname NOT LIKE 'pg%'"
execute "CREATE SCHEMA #{schema}" unless schemas.include?(schema)
# 设置一下search_path,让建表操作优先在指定的schema内执行
re = execute "SHOW search_path"
execute "SET search_path TO #{schema}, #{re.result}"
yield
execute "SET search_path TO #{re.result}"
end
end
代码很简单,关键就在于search_path的设置。它把指定的模式(本文例子中的project)放在前面,后面才是原来的search_path。
但这样做有个问题。比如这段代码:
run_in_schema :project do
drop_table :categories
end
这是一个删除categories表的操作。如果此时project模式中没有该表,但public模式中有的话,则会删除public模式下的categories表。原因就在于search_path中还是有public模式,只是搜索顺序靠后了一点。
那修改search_path的时候,只加入project模式不就完了?之所以不这样做,完全是因为schema_migrations这个表。Rails在执行完每一个migration文件后,都会去更新schema_migrations表。如果找不到,就会抛出异常。所以我不得不把原来的search_path加在进去。这个小bug只要稍加注意,还是没什么问题的。如果有同学知道这个问题的解决方法,请赐教。
参考资料
Creating a multi-tenant application using PostgreSQL's schemas and Rails
本来我是想找找Rails中怎么判断数据库中一个模式是否存在的方法的,然后在这篇文章中找到了解决办法,然后发现他设置search_path的思路和我一样,直接取消了我发到原创博客的想法……
分享到:
相关推荐
guardrails-engine-output-schema-validator --help Usage: guardrails-engine-output-schema-validator [options] Options: -V, --version output the version number -s, --stdin Read from stdin -f, --file...
rails-dev-box, 面向 Ruby on Rails 核心开发的虚拟机 用于 Ruby on Rails 核心开发的虚拟机简介注意:这个虚拟机不是为 Rails 应用程序开发而设计的,只是为。 这个项目自动设置开发环境,以便在 Ruby on Rails ...
标题 "rails-documentation-1-2-1.zip" 暗示这是一份关于 Ruby on Rails 框架的文档,版本为 1.2.1。Ruby 是一种面向对象的编程语言,而 Rails 是一个基于 Ruby 的开源 Web 应用程序框架,遵循 Model-View-...
压缩包中的"rails-development-environment-master.zip"可能是整个项目文件夹,包括`app`(应用代码)、`config`(配置文件)、`db`(数据库相关)、`bin`(可执行脚本)、`lib`(自定义库)、`test`(测试)、`...
在本项目"rails应用--导航栏实例工程"中,我们将探讨如何在Ruby on Rails框架下构建一个实用的导航栏。Rails是一个流行的开源Web应用程序框架,它遵循MVC(模型-视图-控制器)架构模式,使得开发过程更加高效且结构...
scp rails-passenger-postgres-nginx root@SERVER:/root/rails-passenger-postgres-nginx ssh root@SERVER "./rails-passenger-postgres-nginx app_name db_pass" 如果出现错误“ No PostgreSQL clusters exist ...
rails-documentation-2-0-2
rails-beginner-s-guide是Rails 指导手册,帮组学习了解rails开发
官方离线安装包,测试可用。使用rpm -ivh [rpm完整包名] 进行安装
在"rails-react-components-源码"中,我们可以看到如何定义React组件,以及如何通过props传递数据和方法。组件化开发提高了代码的可读性和可维护性,降低了复杂性。 2. **Webpack与Rails的集成** Rails默认使用...
Rails 3.1 和 Cucumber-Rails 1.2.0 是两个在Web开发领域非常重要的工具,尤其对于Ruby on Rails框架的测试和自动化流程。本文将深入探讨这两个组件,以及它们如何协同工作来增强软件开发的效率和质量。 首先,...
`rails-documentation-2-0-2.chm` 文件详细涵盖了这些概念,包含了关于Rails 2.0.2的API参考、教程和指南。通过仔细阅读和实践,开发者能够深入理解Rails的工作原理,并有效地开发出高效、可维护的Web应用。
### Ruby on Rails Guides v2 - Ruby on Rails 4.2.5 #### 一、重要概念及基础假设 - **重要概念**:本指南旨在帮助...随着对Rails的深入了解,你将会发现更多高级特性和应用场景,为实际项目开发提供更多可能性。
用于Ruby on Rails核心开发的虚拟机 介绍 请注意,该虚拟机并非为...host $ cd rails-dev-box host $ vagrant up 而已。 安装完成后,您可以使用以下命令访问虚拟机: host $ vagrant ssh Welcome to Ubuntu 20.10
rails-documentation-1-2-0-rc1.chm
在描述中,"rails-yelp-mvp-源码.rar" 提示这是一个压缩文件,包含了构建一个Yelp类似功能的Web应用的全部源代码。通常,这样的项目会包含模型(Models)、视图(Views)和控制器(Controllers),以及数据库迁移...
rails-ftw-v0.18-2.1.5-4.1.8.exe用于在windows环境下搭建readmine环境
总的来说,Rails 4.2.0和Ruby 4.2.0的组合为开发者提供了强大而稳定的开发平台,而`rails_setup`文件则是一个宝贵的资源,帮助开发者快速搭建和配置环境。通过学习和理解这些知识点,开发者可以更高效地利用Rails...
在"rails-playlists-源码"中,我们可能会看到代表播放列表和歌曲的ActiveRecord模型。 3. **路由(Routing)** Rails的路由系统将HTTP请求映射到控制器的特定动作上。在`config/routes.rb`文件中,开发者定义了URL...
3. 文件生成与下载:Rails 内置的 send_data 和 send_file 方法可用于在服务器端生成文件后发送到客户端下载。 五、源码学习步骤 1. 阅读项目 README 文件,了解基本用法和安装步骤。 2. 分析 models 文件,理解...