Rails中基于动态数据库的路由可防止schema:load

时间:2018-07-24 09:08:24

标签: ruby-on-rails

我们刚刚从新客户端继承了代码库,并且正在将其引入我们的系统中。

rake db:schema:load命令存在一个小问题,由于routes.rb文件中的以下几行而导致失败:

if Rails.env.development? || Rails.env.staging?
  Country.all.each do |country|
    get "/#{country.locale}", to: 'home_pages#index', locale: country.locale
  end
end

如您所见,这是在检查我们是否处于开发环境中,然后尝试为数据库中的每个国家/地区动态生成路线-但是,由于数据库中没有国家/地区,这当然会失败

经典渔获22;)

我希望找出的是是否有某种方法可以避免这种情况的发生?我可以暂时将routes.rb文件中的违规行注释掉,但这有点像作弊,并且认为必须有一种更优雅的方法。

谢谢。

2 个答案:

答案 0 :(得分:1)

我可以看到2种可能的解决方案:

1定义具有约束的动态路线

get '/:locale', to: 'home_pages#index', constraint: -> { |req| Country.where(locale: req.parameters[:locale]).exists? }

注意:您不再需要locale: country_locale,因为:locale(在路由声明中)将为您提供此参数,该参数可在请求对象中使用。

约束lambda技巧的作用是-加载应用程序后检查所请求路线的有效性(因此,在加载和评估路线文件时,公司不必位于数据库中)。

缺点是,每当有匹配该路由的请求时,数据库就会受到额外的打击。也许您可以通过一些缓存缓解它。

好处是,您现在可以在运行时添加具有新语言环境的新国家(无需重新启动应用程序),但是我想这不是主要问题。

2将语言环境转储到文件中,并使其与数据库同步

您可以保留创建路由的方式(遍历所有语言环境并为每个语言定义一个路由),但是可以从文件中加载语言环境。

File.open('locales.txt').each_line do |locale|
  get "/#{locale}", to: 'home_pages#index', locale: locale
end

缺点是您需要保持同步(是否出现一些新的国家/消失的情况?)您有时可以将Company.pluck(:locale).join("\n")转储到此文件中。

我觉得这个特定的rake任务不需要定义路由,但是可能是Rails应用程序环境的加载方式。我遇到了同样的问题(我们在缓存BTW中使用了解决方案1),我想我在某处报告了该问题,但是我找不到它...成功后会共享。

答案 1 :(得分:0)

我的同事发现的一个答案是在运行代码之前通过ActiveRecord::Base.connection进行检查以查看数据库表是否存在。

现在看起来像这样:

if (Rails.env.development? || Rails.env.staging? || Rails.env.uat?) && ActiveRecord::Base.connection.table_exists?('countries')
  Country.all.each do |country|
    get "/#{country.locale}", to: 'home_pages#index', locale: country.locale
  end
end
相关问题