ruby-on-rails 路径约束中的Rails活动记录/数据库数据

hpxqektj  于 2023-08-08  发布在  Ruby
关注(0)|答案(2)|浏览(131)

所以我最近通过添加一些Constraint类来整理Rails应用程序中的很多路由约束。大多数情况下,它已经很好地模块化、枯燥、易懂,所以我可能会在未来的开发中坚持使用这种模式。
我想知道从Constraint类中查询Active Record数据是否是一种“坏习惯”。例如,考虑以下类:

class CategoryConstraint
  include DisplayConstraintHelper

  def initialize
    @names = Category.table_exists? ? Category.pluck(:name) : []
  end

  def matches?(request)    
    @names.include?(request.path_parameters[:category]) && display_matches?(request)
  end
end

字符串
今天我发现我需要在上面的initialize方法中使用table_exists?,因为每次我运行rake任务时都会调用我的路由- * 比如设置开发数据库 *。如果数据库还不存在,而应用程序已经加载,则pluck调用会抛出错误,因为表还不存在。
虽然调用table_exists?可能不昂贵,但我很担心它会在生产中为每一个请求调用,当应用程序启动后,表不存在的机会。这让我开始怀疑使用Active Record表中的数据创建路由约束是否是一个坏主意。
我确实希望我的路由限制在这些值,虽然,值可以根据网站内容管理而改变(所以硬编码是愚蠢的)。我希望用户得到一个404时,他们使用一个无效的类别名称,而不是我的网站加载正常,并说“对不起,没有项目的类别 XYZ。”因此,我坚持的问题,需要这个table_exists?调用,为初始的prod部署,为新的开发人员设置和环境第一次,并为任何人下降和设置一个新的数据库的网站。
这看起来像一个坏习惯吗?如果我想让应用程序在数据库未设置时按预期运行,这是否只是我不得不忍受的事情?
有人知道更好的替代方案吗?

vecaoik1

vecaoik11#

我在应用程序中有这样的限制:

scope '/:slug', constraints: lambda { |request| Class.find_by_slug(request.params[:slug]).present? } do

字符串
在这个作用域内,我有一个路由globbing,所以除了使用这个约束,我不能做任何其他事情,因为slugs是由用户创建的动态资源。
我认为这是一个解决问题的工具,所以如果它是你知识最高的更好的选择,那就用它吧!
从所有这些,我明白你的应用程序需要数据库,那么你怎么能指望你的应用程序没有数据库也能正常工作呢?

vvppvyoh

vvppvyoh2#

问题更可能是从构造函数(def initialize)中进行数据库查询,该构造函数在定义路由时被调用。
Kadu的答案应该可以正常工作,因为他的db查询是在lambda中进行的,只有当请求传入时才会调用lambda。
如果你可以在每个匹配请求上调用Category.all.pluck(:name),那么你可以在matches?方法中使用相同的约束类:

class CategoryConstraint
  include DisplayConstraintHelper

  def matches?(request)
    Category.pluck(:name).include?(request.path_parameters[:category]) && display_matches?(request)
  end
end

字符串
如果您不需要内存中的所有名字,您最好使用以下方法:

Category.exists?(name: request.path_parameters[:category])


如果你的目标是在内存中缓存所有的名字,这样你就不用在每次调用中都进行查询,你可以在类级别延迟赋值:

class CategoryConstraint
  include DisplayConstraintHelper

  mattr_reader :names, instance_accessor: false

  def matches?(request)
    names.includes(request.path_parameters[:category]) && display_matches?(request)
  end

  def names
    self.class.names ||= Category.pluck(:name)
  end
end


至于在约束中是否可以接受ActiveRecord查询-是的,我认为这是完全可以接受的,并且对于管理员特定的路由来说是个好主意。只是要注意只在#matches?#call方法中执行查询,这样它就发生在请求生命周期中。

相关问题