我试图将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
这是控制器中的show动作:
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
,那确实有效。但是,如果没有,我得到错误:&#34; API :: V1中的NoMethodError :: ProjectsController #index undefined method []' 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 the
active_model_serializers` gem。
答案 0 :(得分:1)
所有数据库逻辑都属于您的模型,而不是您的序列化程序。序列化器只是说明应该暴露什么,但它不应该负责计算它。
所以在这里,我建议在您的模型上使用another_id
方法,这不会解决您的问题(因为它似乎更像是一个SQL问题而不是其他任何东西),但它会使它如此你不再有AMS的问题了。
答案 1 :(得分:0)
序列化程序获取记录并返回适合JSON或XML编码的序列化表示。
它们可以替代乱丢你的控制器:
$('#link-title').on('click', function(){
window.open('https://linkaddress.com','_blank');
window.open('https://linkaddresstwo.com','_blank');
});
和jbuilder的精神胀气。
SQL查询和范围改为属于您的模型。
您可以使用render json: @users, except: [:foo, :bar, :baz], include: [..........]
选项设置序列化程序。但是在这种情况下,序列化的对象必须至少实现the base methods for a serializable model,这对你没有多大帮助。
因此,您需要重新编写查询,以便返回一个集合或记录数组。
见:
答案 2 :(得分:0)
知道了!看来我在序列化器中还需要一个方法:
<强> project_serializer.rb 强>
def another_id
object.another_id
end
def another_id__sql
# sql from before
end
我并非100%确定为什么会这样,但我注意到,如果我遗漏了another_id__sql
,我会收到错误column.projects.another_id does not exist
。所以,我猜测another_id__sql
在返回数组时被调用,但在another_id
是单个项目记录时使用object
方法。< / p>
我仍然希望听到更好的方法来做到这一点!