【发布时间】:2015-10-20 18:45:54
【问题描述】:
我正在尝试返回相关记录的 another_id。我只想为每个项目添加一个 has_many 和 belongs_to 关系,但我需要有用户 ID 才能返回正确的结果。但是,使用下面的代码,它会返回 current_user 的所有可能的 another_ids。
如果我将它输入到 psql 中,它可以正常工作:
WITH RECURSIVE t(id, parent_id, path) AS (
SELECT thing.id, thing.parent_id, ARRAY[thing.id]
FROM thing, projects
WHERE thing.id = 595
UNION
SELECT i.id, i.parent_id, i.parent_id || t.path
FROM thing i
INNER JOIN t ON t.parent_id = i.id
)
SELECT DISTINCT user_thing.another_id FROM user_thing
INNER JOIN t on t.id = user_thing.thing_id
WHERE t.id = user_thing.thing_id AND user_thing.user_id = 2;
another_id
-----------
52
(1 row)
但如果我从序列化程序运行代码,它会返回:[52, 51]:
class ProjectSerializer < ActiveModel::Serializer
attributes :id, :another_id
def another_id__sql
"(WITH RECURSIVE t(id, parent_id, path) AS (
SELECT thing.id, thing.parent_id, ARRAY[thing.id]
FROM thing, projects
WHERE thing.id = projects.thing_id
UNION
SELECT i.id, i.parent_id, i.parent_id || t.path
FROM thing i
INNER JOIN t ON t.parent_id = i.id
)
SELECT DISTINCT user_thing.another_id FROM user_thing
INNER JOIN t on t.id = user_thing.thing_id
WHERE t.id = user_thing.thing_id AND user_thing.user_id = #{options[:current_user].id})"
end
end
class API::V1::ProjectsController < API::APIController
def index
render json: Project.all
end
private
def default_serializer_options
{ current_user: @current_user }
end
end
据我所知,我不了解 active_model_serializers 如何序列化多个记录。
我正在使用 rails 4.2.3 和 active_model_serializers 0.8.3。恐怕我无法更改架构。此外,这可能无关紧要,但这是 Ember 应用程序的 API。
提前致谢。我有点尴尬,我在这方面遇到了麻烦。
编辑:
我应该提一下,这就是我的项目模型的样子:
class Project < ActiveRecord::Base
belongs_to :thing
has_many :user_thing, through: :thing
attr_accessor :another_id
def set_another_id(user)
connection = ActiveRecord::Base.connection
result = connection.execute("(WITH RECURSIVE t(id, parent_id, path) AS (
SELECT thing.id, thing.parent_id, ARRAY[thing.id]
FROM thing, projects
WHERE thing.id = #{thing_id}
UNION
SELECT i.id, i.parent_id, i.parent_id || t.path
FROM thing i
INNER JOIN t ON t.parent_id = i.id
)
SELECT DISTINCT user_thing.another_id FROM user_thing
INNER JOIN t on t.id = user_thing.thing_id
WHERE t.id = user_thing.thing_id AND user_thing.user_id = #{user.id})")
@another_id = result[0]["another_id"].to_i
end
end
这是控制器中的显示动作:
def show
@project = Project.find(params[:id])
@project.set_another_id(@current_user)
render json: @project
end
show 操作确实返回了正确的 id。
另外,我知道我所拥有的是不正确的。问题是我不能只使用 activerecord 关联,因为它取决于该会话的当前用户。
编辑 2:
我认为如果我只是使用 我错了!请参阅下面的答案。render json: Project.all.to_json 渲染它,我就能让它工作,并摆脱了序列化程序中的 another_id__sql 方法。如果它确实有another_id,那确实有效。但是,如果那是 nil,我会收到错误消息:“API::V1::ProjectsController#index 未定义方法 []' for nil:NilClass". It looks like this is a possible bug in 0.8, so I'll either have to ask another Stack Overflow question, or I'll have to see if I can upgrade theactive_model_serializers` gem 中的 NoMethodError。
【问题讨论】:
-
你说它没有返回正确的ID。它究竟返回了什么?错误记录的 ID?
-
更多问题:如果您在用户 ID 中硬编码,它是否返回正确的 ID? SQL(Rails 之外)是否始终如一地为不同的记录返回正确的 ID,或者它是否可能实际上无法正常工作但碰巧为该特定记录返回了正确的 ID?我的一个想法是
result[0]["another_id"]实际上可能返回 nil,而 #to_i 方法会将其转换为 0。结果是 0 吗? -
它返回一个包含该模型所有 id 的数组。比如有两个
anothers:51和52。它应该返回52,但它实际上返回[51, 52]。我知道这是因为我拥有的 SQL 正在寻找所有项目的所有适用记录,但我不知道如何解决。如果我对 thing_id 进行硬编码,SQL 确实可以工作。
标签: ruby-on-rails active-model-serializers