I'm trying to return the another_id for a related record. I would just add a has_many and belongs_to relation for each project, but I need to have the user id in order to return the correct results. However, with the code I have below, it returns all of the possible another_ids for the current_user.
If I enter this into psql, it works fine:
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)
But if I run the code from the serializer, it returns: [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
From what I can gather, I'm not understanding how active_model_serializers serializes more than one record.
I'm using rails 4.2.3 and active_model_serializers 0.8.3. I'm afraid I can't change the schema. Also, it probably doesn't matter, but this is the API for an Ember app.
Thanks in advance. I'm a bit embarrassed that I'm having trouble with this.
Edit:
I should probably mention that this is what my project model looks like:
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
And this is the show action in the controller:
def show
@project = Project.find(params[:id])
@project.set_another_id(@current_user)
render json: @project
end
The show action does return the correct id.
Also, I know what I have is incorrect. The thing is that I can't just use the activerecord associations, because it depends on that session's current user.
Edit 2:
I thought I was able to get it to work if I just rendered it using: I was wrong! See my answer below.render json: Project.all.to_json
, and got rid of the another_id__sql
method in the serializer. That does work if it does have another_id
. However, if that's nil, I get the error: "NoMethodError in API::V1::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.
result[0]["another_id"]
may actually be returning nil and the #to_i method would convert that to 0. Are you getting 0 as the result? – Ravenstineanother
s: 51 and 52. It should return 52, but it actually returns [51, 52]. I know it's because the SQL I have is looking for all applicable records of all projects, but I don't know how to solve that. The SQL does work if I hardcode the thing_id. – NJP