Heroku部署Ruby Active Record插入PostgreSQL时字符串长度限制问题
问题
在Ruby中向Heroku上的PostgreSQL Active Record数据库插入数据时存在字符串长度限制吗?
本地环境中可以向名为Devices的表创建并插入记录,但在Heroku部署环境中,当identifier和push_token的长度过长时无法创建记录。
设备表迁移代码:
class CreateDevices < ActiveRecord::Migration[6.1] def change create_table :devices do |t| t.string :identifier, null: false t.string :push_token, null: false end end end
测试端点代码:
get "\/test\/devices\/:device_id\/:push_tokens" do Device.create(identifier: params[:device_id], push_token: params[:push_tokens]) puts "device_count is" puts Device.count end
本地测试时,使用278b5d5668b7e2df3b686e0c0d19a0b9作为identifier、1319f7e0f6dd345304c5e8e84e5ec3f52213b8f485e4783861b476373f000dde作为push_token,Active Record能正常更新,设备计数增加。但在Heroku部署环境中使用这些值时,计数未更新,记录也未创建。
Heroku测试日志:
2022-09-23T13:47:45.399683+00:00 heroku[router]: at=info method=GET path="\/test\/devices\/123456789123456789\/123456789123456789" host=japsoc-passes-server-2.herokuapp.com request_id=21779202-b9b6-4e02-9195-6ead6cc63ba6 fwd="147.12.186.203" dyno=web.1 connect=0ms service=9ms status=200 bytes=191 protocol=https 2022-09-23T13:47:45.394194+00:00 app[web.1]: device_count is 2022-09-23T13:47:45.395126+00:00 app[web.1]: 8 2022-09-23T13:47:59.284900+00:00 heroku[router]: at=info method=GET path="\/test\/devices\/123456789123456789123456789\/123456789123456789123456789" host=japsoc-passes-server-2.herokuapp.com request_id=04ef6dab-71c3-4237-b52f-bf2ea16576f0 fwd="147.12.186.203" dyno=web.1 connect=0ms service=7ms status=200 bytes=191 protocol=https 2022-09-23T13:47:59.279643+00:00 app[web.1]: device_count is 2022-09-23T13:47:59.280339+00:00 app[web.1]: 9 2022-09-23T13:48:17.720446+00:00 heroku[router]: at=info method=GET path="\/test\/devices\/123456789123456789123456789123456789\/123456789123456789123456789123456789" host=japsoc-passes-server-2.herokuapp.com request_id=1c221b82-f142-44a0-b0ec-774a8515365a fwd="147.12.186.203" dyno=web.1 connect=0ms service=9ms status=200 bytes=191 protocol=https 2022-09-23T13:48:17.715182+00:00 app[web.1]: device_count is 2022-09-23T13:48:17.715917+00:00 app[web.1]: 10 2022-09-23T13:48:35.566064+00:00 heroku[router]: at=info method=GET path="\/test\/devices\/123456789123456789123456789123456789123456789\/123456789123456789123456789123456789123456789" host=japsoc-passes-server-2.herokuapp.com request_id=2539f65b-7f82-42dc-9c4e-c078b93412d1 fwd="147.12.186.203" dyno=web.1 connect=0ms service=6ms status=200 bytes=191 protocol=https 2022-09-23T13:48:35.560941+00:00 app[web.1]: device_count is 2022-09-23T13:48:35.561519+00:00 app[web.1]: 11 2022-09-23T13:49:00.943300+00:00 heroku[router]: at=info method=GET path="\/test\/devices\/123456789123456789123456789123456789123456789123456789\/123456789123456789123456789123456789123456789123456789" host=japsoc-passes-server-2.herokuapp.com request_id=01acc954-8cf9-4327-8e84-b1958298b14d fwd="147.12.186.203" dyno=web.1 connect=0ms service=8ms status=200 bytes=191 protocol=https 2022-09-23T13:49:00.937948+00:00 app[web.1]: device_count is 2022-09-23T13:49:00.938685+00:00 app[web.1]: 12 2022-09-23T13:49:52.814962+00:00 heroku[router]: at=info method=GET path="\/test\/devices\/123456789123456789123456789123456789123456789123456789\/123456789123456789123456789123456789123456789123456789123456789123456789" host=japsoc-passes-server-2.herokuapp.com request_id=c834c2df-b822-4796-b8ae-ab29cce6bdc2 fwd="147.12.186.203" dyno=web.1 connect=0ms service=5ms status=200 bytes=191 protocol=https 2022-09-23T13:49:52.809811+00:00 app[web.1]: device_count is 2022-09-23T13:49:52.810427+00:00 app[web.1]: 12
从日志可见,当identifier或push_token字符串过长时,记录未创建但返回200状态码。
解决方案
原因分析
- Active Record
string类型默认长度限制:Rails中t.string默认映射PostgreSQL的varchar(255)类型,插入字符串超过255字符时,PostgreSQL会抛出截断错误,但Device.create会捕获错误并返回false,不会主动抛出异常,导致无错误提示但记录未创建。 - 本地与Heroku环境差异:本地通常使用SQLite,其
TEXT类型无严格长度限制,即使定义string也能插入超长内容;而Heroku的PostgreSQL严格遵循varchar(255)的长度规则。
解决步骤
- 修改数据库字段类型:创建新迁移,将
identifier和push_token改为无长度限制的text类型:
class ChangeDevicesColumnsToText < ActiveRecord::Migration[6.1] def change change_column :devices, :identifier, :text, null: false change_column :devices, :push_token, :text, null: false end end
- 部署迁移到Heroku:
git add db/migrate/[你的迁移文件名] git commit -m "Change devices identifier and push_token to text type" git push heroku main heroku run rails db:migrate
- 优化测试端点的错误反馈:修改端点代码,检查创建结果并返回明确状态码和错误信息,便于调试:
get "\/test\/devices\/:device_id\/:push_tokens" do device = Device.new(identifier: params[:device_id], push_token: params[:push_tokens]) if device.save puts "device_count is #{Device.count}" status 201 else puts "Failed to create device: #{device.errors.full_messages}" status 400 body device.errors.full_messages.join(', ') end end
修改后,超长字符串可正常插入Heroku的PostgreSQL数据库,同时端点会返回明确的错误信息辅助调试。
内容的提问来源于stack exchange,提问作者Korokus
相关产品推荐
相关产品推荐

