Skip to content

Commit

Permalink
Use our optimized decorators to serialize pages
Browse files Browse the repository at this point in the history
BREAKING: This removes the all_elements relation from the includable
relationships and uses an eager loaded elements
collection that includes all publicly available elements from that page.

Use client side filtering and grouping to seperate fixed ones from
other elements and use a deserializer that supports
nesting.
  • Loading branch information
tvdeyen committed Jan 19, 2021
1 parent 0755ffe commit 58758b3
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 27 deletions.
9 changes: 5 additions & 4 deletions app/controllers/alchemy/json_api/pages_controller.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# frozen_string_literal: true

module Alchemy
module JsonApi
class PagesController < JsonApi::BaseController
Expand Down Expand Up @@ -48,15 +49,15 @@ def page_scope
def page_scope_with_includes
base_page_scope.
with_language(Language.current).
preload(language: {nodes: [:parent, :page]}, all_elements: [:parent_element, :nested_elements, { contents: { essence: :ingredient_association } }])
preload(language: { nodes: [:parent, :page] }, elements: { contents: { essence: :ingredient_association } })
end

def base_page_scope
# cancancan is not able to merge our complex AR scopes for logged in users
if can?(:edit_content, Page)
Page.all
if can?(:edit_content, ::Alchemy::Page)
::Alchemy::JsonApi::Page.all
else
Page.published
::Alchemy::JsonApi::Page.published
end
end

Expand Down
14 changes: 7 additions & 7 deletions app/serializers/alchemy/json_api/page_serializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,16 @@ class PageSerializer
)

belongs_to :language, record_type: :language, serializer: ::Alchemy::JsonApi::LanguageSerializer

has_many :elements, record_type: :element, serializer: ::Alchemy::JsonApi::ElementSerializer
has_many :fixed_elements, record_type: :element, serializer: ::Alchemy::JsonApi::ElementSerializer

has_many :all_elements, record_type: :element, serializer: ::Alchemy::JsonApi::ElementSerializer do |page|
page.all_elements.select { |e| e.public? && !e.trashed? }
end

with_options if: ->(_, params) { params[:admin] == true } do
attribute :tag_list
attribute :tag_list do |page|
Gutentag::Tagging.where(
taggable_id: page.id,
taggable_type: "Alchemy::Page",
).joins(:tag).pluck("gutentag_tags.name")
end

attribute :status
end
end
Expand Down
2 changes: 1 addition & 1 deletion spec/requests/alchemy/json_api/pages_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
let(:element) { FactoryBot.create(:alchemy_element, name: "article", autogenerate_contents: true) }

it "includes the data" do
get alchemy_json_api.page_path(page, include: "all_elements.essences")
get alchemy_json_api.page_path(page, include: "elements.essences")
included = JSON.parse(response.body)["included"]
expect(included).to include(have_type("element").and(have_id(element.id.to_s)))
end
Expand Down
29 changes: 14 additions & 15 deletions spec/serializers/alchemy/json_api/page_serializer_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
require "alchemy/test_support/factories"

RSpec.describe Alchemy::JsonApi::PageSerializer do
let(:page) do
let(:alchemy_page) do
FactoryBot.create(
:alchemy_page,
urlname: "a-page",
Expand All @@ -14,6 +14,7 @@
)
end
let(:options) { {} }
let(:page) { Alchemy::JsonApi::Page.find(alchemy_page.id) }

subject(:serializer) { described_class.new(page, options) }

Expand Down Expand Up @@ -52,22 +53,20 @@
end

describe "relationships" do
let(:element) { FactoryBot.create(:alchemy_element) }
let(:fixed_element) { FactoryBot.create(:alchemy_element, fixed: true) }
let(:trashed_element) { FactoryBot.create(:alchemy_element, :trashed) }
subject { serializer.serializable_hash[:data][:relationships] }
let!(:element) { FactoryBot.create(:alchemy_element, page: alchemy_page) }
let!(:fixed_element) { FactoryBot.create(:alchemy_element, page: alchemy_page, fixed: true) }
let!(:non_public_element) { FactoryBot.create(:alchemy_element, page: alchemy_page, public: false) }
let!(:trashed_element) { FactoryBot.create(:alchemy_element, page: alchemy_page).tap(&:trash!) }

before do
page.all_elements << element
page.all_elements << fixed_element
page.all_elements << trashed_element
trashed_element.trash!
end
subject { serializer.serializable_hash[:data][:relationships] }

it "has the right keys and values, and does not include trashed elements" do
expect(subject[:elements]).to eq(data: [{ id: element.id.to_s, type: :element }])
expect(subject[:fixed_elements]).to eq(data: [{ id: fixed_element.id.to_s, type: :element }])
expect(subject[:all_elements]).to eq(data: [{ id: element.id.to_s, type: :element }, { id: fixed_element.id.to_s, type: :element }])
it "has the right keys and values, and does not include trashed or hidden elements" do
expect(subject[:elements]).to eq(
data: [
{ id: element.id.to_s, type: :element },
{ id: fixed_element.id.to_s, type: :element },
],
)
expect(subject[:language]).to eq(data: { id: page.language_id.to_s, type: :language })
end
end
Expand Down

0 comments on commit 58758b3

Please sign in to comment.