Rails 5.1.4升级至5.2.0后Scope触发废弃警告求助
解决Rails 5.2升级后Scope触发的废弃警告问题
嘿,这个问题我太熟了!Rails 5.2对查询安全性做了强化,你遇到的警告就是因为这个变化导致的。让我给你拆解下原因和解决办法:
为啥会出警告?
你用的subtree_ids是ancestry gem提供的方法,它生成的SQL里包含了coalesce("categories"."ancestry", '')这段原始SQL。Rails 5.2开始会严格检查这类非属性参数的查询调用,担心有SQL注入风险,所以抛出了废弃警告。
怎么解决?这里有几个靠谱的方案:
方案1:重写Scope,用关联查询替代ID列表查询
别先拉取子树ID再查了,直接通过关联关系筛选,让Rails帮你处理安全的查询语句:
scope :by_category, lambda { |category_slug| category = Category.find_by(slug: category_slug) return none unless category # 直接关联category表,筛选属于该分类子树的记录 joins(:category).where(category: category.subtree) }
如果这样还触发警告,说明category.subtree的SQL还是没被Rails识别,那咱们用Arel手动构建子树条件,彻底避开原始SQL的问题:
scope :by_category, lambda { |category_slug| category = Category.find_by(slug: category_slug) return none unless category categories_table = Category.arel_table # 基础条件:匹配分类本身 base_condition = categories_table[:id].eq(category.id) # 子节点条件:根据分类是否有父节点,匹配对应的ancestry路径 ancestry_condition = if category.ancestry.present? categories_table[:ancestry].matches("#{category.ancestry}/#{category.id}/%") else categories_table[:ancestry].matches("#{category.id}/%") end # 合并条件:要么是分类本身,要么是它的子节点 subtree_condition = base_condition.or(ancestry_condition) # 关联category表并应用条件 joins(:category).where(subtree_condition) }
方案2:升级ancestry gem到兼容版本
老版本的ancestry没适配Rails 5.2的新规则,升级到最新稳定版(比如4.x系列)就能解决问题。修改你的Gemfile:
gem 'ancestry', '~> 4.0' # 可以去rubygems看最新版本号
然后跑bundle update ancestry,之后原来的scope应该就不会再弹警告了。
方案3:临时禁用警告(不推荐)
如果以上方案暂时没法实施,你可以临时把警告关掉,但这相当于绕过了Rails的安全检查,不建议长期用:
scope :by_category, lambda { |category_slug| category_ids = ActiveRecord::Base.silence_deprecation do Category.find_by(slug: category_slug)&.subtree_ids end where(category_id: category_ids) }
总结
优先选方案2(升级gem)或者方案1(重写scope),既能解决警告,又能保证查询的安全性和性能,完美适配Rails 5.2的规则~
内容的提问来源于stack exchange,提问作者Mateusz Urbański
相关产品推荐
相关产品推荐

