Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Spike use of presenters during serialization #950

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 5 additions & 9 deletions app/blueprints/contribution_blueprint.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,10 @@ class ContributionBlueprint < Blueprinter::Base
contribution.created_at.to_f * 1000 # Javascript wants miliseconds, not seconds
end
field :type, name: :contribution_type
field :profile_path do |contribution, options|
options[:profile_path]&.call(contribution.person_id)
end
field :view_path do |contribution, options|
options[:view_path]&.call(contribution.id)
end
field :match_path do |contribution, options|
options[:match_path]&.call(contribution.id)
end
field :view_path
association :person, blueprint: PersonBlueprint

# FIXME: profile_path and match_path appear to be unused; remove from here and front end
field(:profile_path) { nil }
field(:match_path) { nil }
end
8 changes: 1 addition & 7 deletions app/controllers/contributions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class ContributionsController < ApplicationController
def index
@filter_types = FilterTypeBlueprint.render([ContributionType, Category, ServiceArea, UrgencyLevel, ContactMethod])
filter = BrowseFilter.new(filter_params)
@contributions = ContributionBlueprint.render(filter.contributions, contribution_blueprint_options)
@contributions = ContributionBlueprint.render(ContributionPresenter.map(filter.contributions, self))
respond_to do |format|
format.html
format.json { render inline: @contributions }
Expand Down Expand Up @@ -45,12 +45,6 @@ def peer_to_peer_mode?
@system_setting.peer_to_peer?
end

def contribution_blueprint_options
options = {}
options[:view_path] = ->(id) { contribution_path(id) }
options
end

def filter_params
return {} unless allowed_params&.to_h.any?

Expand Down
2 changes: 1 addition & 1 deletion app/javascript/pages/browse/ListBrowser.vue
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
<a :href="contribution.view_path" class="button icon-list is-primary"><span class=""> View</span></a>
</div>
</td>
<td>{{ contribution.person.name.split(" (")[0] }}</td>
<td>{{ contribution.person.name }}</td>
<!-- <td>{{ contribution.title }}</td>-->
</tr>
</table>
Expand Down
2 changes: 1 addition & 1 deletion app/javascript/pages/browse/TileListItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
{{ service_area.name }}
</div>
<div>
{{ `From: ${person.name.split(" (")[0]}` }}
{{ `From: ${person.name}` }}

</div>
</div>
Expand Down
4 changes: 4 additions & 0 deletions app/presenters/base_presenter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ class BasePresenter < SimpleDelegator
delegate :context, to: :h
alias_method :object, :__getobj__

def self.map collection, view_context
collection.map { |object| new(object, view_context) }
end

def initialize object, view_context
super object
@h = view_context
Expand Down
9 changes: 9 additions & 0 deletions app/presenters/contribution_presenter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class ContributionPresenter < BasePresenter
def view_path
h.contribution_path id
end

def person
PersonPresenter.new(super, h)
end
end
11 changes: 11 additions & 0 deletions app/presenters/person_presenter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
class PersonPresenter < BasePresenter
def name
policy.read? ? super : nil
end

private

def policy
@policy ||= PersonPolicy.new context, object
end
end
21 changes: 6 additions & 15 deletions spec/blueprints/contribution_blueprint_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
urgency_level_id: 1
)
end
let(:presenter) do
ContributionPresenter.new(contribution, double('ViewContext', contribution_path: '/fake/contribution/path', context: Context.new))
end
let(:expected_contact_method) { contribution.person.preferred_contact_method }
it 'returns reasonable data by default' do
expected_area_name = Faker::Address.community
Expand All @@ -29,11 +32,11 @@
# "publish_until" => "2021-10-11",
# "publish_until_humanized" => "this year",
'created_at' => (contribution.created_at.to_f * 1000), # Javascript wants miliseconds, not seconds
'view_path' => nil,
'view_path' => '/fake/contribution/path',
'profile_path' => nil,
'match_path' => nil,
'name' => contribution.name,
'person' => { 'id' => contribution.person.id, 'name' => contribution.person.name, 'email' => contribution.person.email,
'person' => { 'id' => contribution.person.id, 'name' => nil, 'email' => contribution.person.email,
'phone' => contribution.person.phone, 'skills' => contribution.person.skills,
'preferred_contact_method' => { 'id' => contribution.person.preferred_contact_method.id, 'name' => contribution.person.preferred_contact_method.name }},
'location' => nil,
Expand All @@ -44,19 +47,7 @@
'contact_types' => [{ 'id' => expected_contact_method.id, 'name' => expected_contact_method.name }]
}]
}
result = ContributionBlueprint.render([contribution], root: 'contributions')
result = ContributionBlueprint.render([presenter], root: 'contributions')
expect(JSON.parse(result)).to match(expected_data)
end

it 'allows injecting a url formatter for the view_path' do
expected_path = "/testing_#{contribution.id}"
result = ContributionBlueprint.render(contribution, view_path: ->(p_id) { "/testing_#{p_id}"})
expect(JSON.parse(result)['view_path']).to eq(expected_path)
end

it 'allows injecting a url formatter for the profile_path' do
expected_path = "/testing_#{contribution.person.id}"
result = ContributionBlueprint.render(contribution, profile_path: ->(p_id) { "/testing_#{p_id}"})
expect(JSON.parse(result)['profile_path']).to eq(expected_path)
end
end
24 changes: 24 additions & 0 deletions spec/presenters/person_presenter_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
require 'rails_helper'

RSpec.describe PersonPresenter do
let(:person) { build :person, name: 'James Brown' }
let(:context) { Context.new user: current_user }
let(:view_context) { double 'ViewContext', context: context }
let(:presenter) { PersonPresenter.new person, view_context }

describe 'name' do
subject { presenter.name }

context 'when current user is authorized to see people names' do
let(:current_user) { build :user, :admin }

it { is_expected.to eql 'James Brown' }
end

context 'when current user is not authorized to see people names' do
let(:current_user) { build :user, :neighbor }

it { is_expected.to be nil }
end
end
end