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

Feature/add method handling expansion child objects #1063

Draft
wants to merge 8 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 4 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
1 change: 1 addition & 0 deletions app/controllers/api/api_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ class Api::ApiController < ActionController::Base # rubocop:disable Rails/Applic
# We disable Rails/ApplicationController bec
include Controllers::Locale
include Controllers::Nonprofit::Authorization
include Controllers::Api::JbuilderExpansions

rescue_from ActiveRecord::RecordInvalid, with: :record_invalid_rescue
rescue_from AuthenticationError, with: :unauthorized_rescue
Expand Down
2 changes: 2 additions & 0 deletions app/controllers/api/transactions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ class Api::TransactionsController < Api::ApiController
# Gets the nonprofits supporters
# If not logged in, causes a 401 error
def index
set_expansions('supporter', 'subtransaction.payments', 'transaction_assignments', 'payments')
@transactions = current_nonprofit.transactions.order('created DESC').page(params[:page]).per(params[:per])
end

# Gets the a single nonprofit supporter
# If not logged in, causes a 401 error
def show
set_expansions('supporter', 'subtransaction.payments', 'transaction_assignments', 'payments')
@transaction = current_transaction
end

Expand Down
167 changes: 167 additions & 0 deletions app/controllers/concerns/controllers/api/jbuilder_expansions.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
# frozen_string_literal: true

# License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later
# Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE
module Controllers::Api::JbuilderExpansions
extend ActiveSupport::Concern
included do
@__expand = Controllers::Api::JbuilderExpansions::ExpansionRequest.new

def set_expansions(*expansions)
@__expand = Controllers::Api::JbuilderExpansions.set_expansions(*expansions)
end

def request_expansions(*expansions)
Controllers::Api::JbuilderExpansions.set_expansions(*expansions)
end

def handle_expansion(attribute, object, opts = {})
opts = opts.deep_symbolize_keys
opts[:__expand] ||= __expand
ExpansionRequestProcessor.handle_expansion(attribute, object, opts)
end

def handle_array_expansion(attribute, object, opts = {}, &block)
opts[:__expand] ||= __expand
ExpansionRequestProcessor.handle_array_expansion(attribute, object, opts, &block)
end

def handle_item_expansion(object, opts = {})
opts[:__expand] ||= __expand
ExpansionRequestProcessor.handle_item_expansion(object, opts)
end

helper_method :handle_expansion, :handle_array_expansion, :handle_item_expansion, :request_expansions
end

def self.set_expansions(*expansions)
request = ExpansionRequest.new
expansions = expansions.flatten
if expansions.count == 1
if expansions.first.is_a? String
request = ExpansionRequest.new(*expansions)
elsif expansions.first.is_a? ExpansionRequest
request = expansions.first
end
elsif expansions.any?
request = ExpansionRequest.new(*expansions)
end

request
end

class ExpansionRequestProcessor
attr_reader :attribute, :object

def initialize(attribute, object, opts)
@attribute = attribute
@object = object
@opts = opts.deep_symbolize_keys
end

def json
@opts[:json]
end

def exp_request
@opts[:__expand]
end

def as
@opts[:as] || attribute
end

def item_as
@opts[:item_as] || attribute
end

def handle_expansion
if object.nil?
json.set! attribute, nil
elsif exp_request.expand? attribute
json.set! attribute do
json.partial! object, as: as, __expand: exp_request[attribute]
end
else
json.set! attribute, object&.id
end
end

def handle_array_expansion
json.set! attribute do
if exp_request.expand? attribute
object.each do |item|
json.child! do
yield(item, { json: json, __expand: exp_request[attribute], as: item_as })
end
end
else
json.array! object.map(&:id)
end
end
end

def handle_item_expansion
json.partial! object, as: as, __expand: exp_request
end

def self.handle_expansion(attribute, object, opts)
ExpansionRequestProcessor.new(attribute, object, opts).handle_expansion
end

def self.handle_array_expansion(attribute, object, opts, &block)
ExpansionRequestProcessor.new(attribute, object, opts).handle_array_expansion(&block)
end

def self.handle_item_expansion(object, opts)
opts = opts.deep_symbolize_keys
ExpansionRequestProcessor.new(nil, object, opts).handle_item_expansion
end
end

class ExpansionRequest
attr_accessor :path_tree

def initialize(*paths)
@path_tree = Node.new
parse_paths(paths)
end

def [](path)
if @path_tree.leaf?
ExpansionRequest.new
else
ExpansionRequest.create_from(@path_tree[path] || Node.new)

end
end

def expand?(path)
@path_tree.has_key?(path)
end

class Node < ActiveSupport::HashWithIndifferentAccess
def leaf?
none?
end
end

private

def parse_paths(paths = [])
paths.each do |path|
working_tree = @path_tree
path.split('.').each do |path_part|
working_tree[path_part] = Node.new unless working_tree[path_part]
working_tree = working_tree[path_part]
end
end
end

def self.create_from(tree)
er = ExpansionRequest.new
er.path_tree = tree
er
end
end
end
4 changes: 4 additions & 0 deletions app/models/modern_donation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,8 @@ def publish_updated
Houdini.event_publisher.announce(:donation_updated, to_event('donation.updated', :nonprofit, :supporter, :trx).attributes!)
Houdini.event_publisher.announce(:trx_assignment_updated, to_event('trx_assignment.updated', :nonprofit, :supporter, :trx).attributes!)
end

def amount_as_money
Amount.new(amount||0, nonprofit.currency)
end
end
12 changes: 12 additions & 0 deletions app/views/api/modern_donations/_modern_donation.json.jbuilder
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# frozen_string_literal: true

# License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later
# Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE

json.object 'donation'

json.(assignable, :designation)

json.amount do
json.partial! '/api/common/amount', amount: assignable.amount_as_money
end
12 changes: 12 additions & 0 deletions app/views/api/modern_donations/object_events/_base.json.jbuilder
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# frozen_string_literal: true

# License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later
# Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE

json.partial! 'api_new/transaction_assignments/transaction_assignment',
transaction_assignment: event_entity.transaction_assignment,
__expand: request_expansions(
'transaction',
'transaction.transaction_assignments',
'transaction.subtransaction.payments'
)
14 changes: 14 additions & 0 deletions app/views/api/object_events/_object_event.json.jbuilder
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# frozen_string_literal: true

# License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later
# Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE

json.id object_event.houid
json.created object_event.created.to_i
json.object 'object_event'
json.type object_event.event_type
json.data do
json.object do
json.partial! partial_path, event_entity: object_event.event_entity
end
end
5 changes: 5 additions & 0 deletions app/views/api/object_events/generate.json.jbuilder
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# frozen_string_literal: true

# License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later
# Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE
json.partial! @object_event, as: :object_event, object_as: @object_as, partial_path: @partial_path
13 changes: 13 additions & 0 deletions app/views/api/object_events/index.json.jbuilder
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# frozen_string_literal: true

# License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later
# Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE
json.data do
json.array! @object_events.map(&:object_json)
end

json.current_page @object_events.current_page
json.first_page @object_events.first_page?
json.last_page @object_events.last_page?
json.requested_size @object_events.limit_value
json.total_count @object_events.total_count
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# frozen_string_literal: true

# License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later
# Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE

json.partial! 'api_new/subtransaction_payments/subtransaction_payment',
subtransaction_payment: event_entity.subtransaction_payment,
__expand: request_expansions(
'subtransaction',
'subtransaction.transaction',
'subtransaction.transaction.transaction_assignments'
)
16 changes: 16 additions & 0 deletions app/views/api/simple_objects/_simple_object.json.jbuilder
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# frozen_string_literal: true

# License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later
# Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE

json.id object.houid

json.object 'simple_object'

handle_expansion(:parent, object.parent, { json: json, as: :object, __expand: __expand })

handle_expansion(:nonprofit, object.nonprofit, { json: json, __expand: __expand })

handle_array_expansion(:friends, object.friends, { json: json, item_as: :object, __expand: __expand }) do |friend, opts|
handle_item_expansion(friend, opts)
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# frozen_string_literal: true

# License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later
# Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE

json.partial! event_entity, as: :object, __expand: request_expansions('parent')
5 changes: 5 additions & 0 deletions app/views/api/simple_objects/show.json.jbuilder
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# frozen_string_literal: true

# License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later
# Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE
json.partial! @simple_object, as: :object, __expand: @__expand
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# frozen_string_literal: true

# License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later
# Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE

json.object 'stripe_transaction_charge'

json.net_amount do
json.partial! '/api_new/common/amount', amount: paymentable.net_amount_as_money
end

json.gross_amount do
json.partial! '/api_new/common/amount', amount: paymentable.gross_amount_as_money
end

json.fee_total do
json.partial! '/api_new/common/amount', amount: paymentable.fee_total_as_money
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# frozen_string_literal: true

# License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later
# Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE

json.partial! 'api_new/subtransaction_payments/subtransaction_payment',
subtransaction_payment: event_entity.subtransaction_payment,
__expand: request_expansions(
'subtransaction.payments',
'subtransaction.transaction.transaction_assignments'
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# frozen_string_literal: true

# License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later
# Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE

json.object 'stripe_transaction_dispute_reversal'

json.net_amount do
json.partial! '/api_new/common/amount', amount: paymentable.net_amount_as_money
end

json.gross_amount do
json.partial! '/api_new/common/amount', amount: paymentable.gross_amount_as_money
end

json.fee_total do
json.partial! '/api_new/common/amount', amount: paymentable.fee_total_as_money
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't believe this file has anything to do with the specific change.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# frozen_string_literal: true
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't believe this file has anything to do with the specific change.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!


# License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later
# Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE

json.partial! 'api_new/subtransaction_payments/subtransaction_payment',
subtransaction_payment: event_entity.subtransaction_payment,
__expand: request_expansions(
'subtransaction',
'subtransaction.transaction',
'subtransaction.transaction.transaction_assignments'
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# frozen_string_literal: true
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't believe this file has anything to do with the specific change.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!


# License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later
# Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE

json.object 'stripe_transaction_dispute'

json.net_amount do
json.partial! '/api_new/common/amount', amount: paymentable.net_amount_as_money
end

json.gross_amount do
json.partial! '/api_new/common/amount', amount: paymentable.gross_amount_as_money
end

json.fee_total do
json.partial! '/api_new/common/amount', amount: paymentable.fee_total_as_money
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# frozen_string_literal: true
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't believe this file has anything to do with the specific change.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!


# License: AGPL-3.0-or-later WITH WTO-AP-3.0-or-later
# Full license explanation at https://github.com/houdiniproject/houdini/blob/main/LICENSE

json.partial! 'api_new/subtransaction_payments/subtransaction_payment',
subtransaction_payment: event_entity.subtransaction_payment,
__expand: request_expansions(
'subtransaction',
'subtransaction.transaction',
'subtransaction.transaction.transaction_assignments'
)
Loading