Custom filters sometimes work incorrectly for nested routes

未关闭
#1,374 1 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

评估

难度
4/5
预计耗时
3-5 天
新手友好度
35/100
Issue 类型
缺陷
描述清晰度
基本清楚
活跃度
停滞
技术栈
rails, ruby
领域
api, backend, database

调研方向

使用内置的 title 过滤器和自定义的 _title 过滤器分别复现嵌套的 /authors/:id/books 请求,然后跟踪自定义过滤器的 apply lambda 如何为嵌套路由接收记录。比较生成的 ActiveRecord join 条件,并根据预期行为添加回归测试或记录表名要求。

由索引模型根据 Issue 内容生成。

描述

This issue is a (choose one):

  • Problem/bug report.
  • Feature request.
  • Request for support. Note: Please try to avoid submitting issues for support requests. Use Gitter instead.

Checklist before submitting:

  • I've searched for an existing issue.
  • I've asked my question on Gitter and have not received a satisfactory answer.
  • I've included a complete bug report template. This step helps us and allows us to see the bug without trying to reproduce the problem from your description. It helps you because you will frequently detect if it's a problem specific to your project.
  • The feature I'm asking for is compliant with the JSON:API spec.

Description

Bug reports:

Gem version 0.10.5.

EDIT: After submitting this, I realized that this might not be considered a bug so much as a limitation due to how ActiveRecord joins work. It might be a good idea, however, to include a caveat in the documentation that table name must be specified in filters so as not to break join queries.

When using a custom filter (i.e. one defined with an apply lambda) on a nested route (/foos/:id/bars), the filter is applied on the parent model (Foo) instead of the child model (Bar), when the child model's table name is not specified in the filter query.

Example:
class AuthorResource < JSONAPI::Resource
  has_many :books
end
class BookResource < JSONAPI::Resource
  has_one :author 
  attributes :title

  filter :title

  filter :_title, apply: ->(records, value, _options){
    records.where(title: value)
  }
end

Rails returns the expected response for http://localhost:3000/authors/1/books?filter[title]=book1:

{"data":[
  {"id":"1",
   "type":"books",
   "links":{
    "self":"http://localhost:3000/books/1"
   },
   "attributes":{
     "title":"book1"
   },
   "relationships":{
     "author":{
       "links":{
         "self":"http://localhost:3000/books/1/relationships/author",
         "related":"http://localhost:3000/books/1/author"}}}}]}

But not for http://localhost:3000/authors/1/books?filter[_title]=book1

{"errors":[
  {"title":"Internal Server Error",
   "detail":"Internal Server Error",
   "code":"500",
   "status":"500",
   "meta":{
     "exception":"SQLite3::SQLException: no such column: authors.title",
     "backtrace":[...],
     "application_backtrace":[]}}]}

So, with filter[title], the filter is applied on Book, whereas with filter[_title], it is is instead applied on Author, in this case causing the error SQLite3::SQLException: no such column: authors.title, since the Author model does not have the attribute title.

filter[_title] does work, however, if we instead define it as:

  filter :_title, apply: ->(records, value, _options){
    records.where(books: {title: value})
  }

So I suppose applying the two versions of _title on records results in something like:

Author.joins(:books).where(title: 'book1')

and

Author.joins(:books).where(books: {title: 'book1'})

respectively, where the first one does not work as intended.

主要语言
Ruby
星标
2.3k
派生
546
PR 合并指标
30 天内没有已合并 PR

贡献指南

这个仓库没有索引到贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

JSONAPI-Resources/jsonapi-resources 的其他 Issue

查看 JSONAPI-Resources/jsonapi-resources 的全部 Issue

相似的 Issue

更多 Ruby Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。