-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from fernandes/feature/contacts_rest_api
Implement /api/v1/contacts REST API
- Loading branch information
Showing
27 changed files
with
546 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
module Api::V1::Contacts::Contract | ||
class Create < Reform::Form | ||
include Api::V1::Contacts::Representer::ContactModule | ||
|
||
validates :first_name, presence: true, length: {minimum: 1} | ||
validates :last_name, presence: true, length: {minimum: 1} | ||
|
||
property :address, populate_if_empty: Address do | ||
include Api::V1::Contacts::Representer::AddressModule | ||
end | ||
|
||
collection :telephones, populate_if_empty: Telephone do | ||
include Api::V1::Contacts::Representer::TelephoneModule | ||
|
||
validates :number, presence: true | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
class Api::V1::Contacts::Create < Trailblazer::Operation | ||
step ->(options, params) { options["representer.render.class"] = Api::V1::Contacts::Representer::Create } | ||
step ->(options, params) { options["representer.errors.class"] = ErrorsRepresenter } | ||
step Model( Contact , :new ) | ||
step Contract::Build(constant: Api::V1::Contacts::Contract::Create) | ||
step Contract::Validate() | ||
step Contract::Persist() | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
class Api::V1::Contacts::Destroy < Trailblazer::Operation | ||
step Model( Contact , :find ) | ||
step ->(options, params) { options[:model].destroy! } | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
class Api::V1::Contacts::Index < Trailblazer::Operation | ||
step ->(options, params) { options["representer.render.class"] = Api::V1::Contacts::Representer::Index } | ||
step ->(options, params) { options["representer.errors.class"] = ErrorsRepresenter } | ||
step ->(options, params) { options[:model] = Contact.all } | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
class Api::V1::Contacts::Show < Trailblazer::Operation | ||
step ->(options, params) { options["representer.render.class"] = Api::V1::Contacts::Representer::Create } | ||
step ->(options, params) { options["representer.errors.class"] = ErrorsRepresenter } | ||
step Rescue(ActiveRecord::RecordNotFound, handler: :not_found_message!) { | ||
step Model( Contact , :find ) | ||
} | ||
|
||
def not_found_message!(exception, options) | ||
options[:error] = { | ||
"message": "Not Found", | ||
"documentation_url": "to be documented" | ||
} | ||
end | ||
|
||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
class Api::V1::Contacts::Update < Trailblazer::Operation | ||
step ->(options, params) { options["representer.render.class"] = Api::V1::Contacts::Representer::Create } | ||
step ->(options, params) { options["representer.errors.class"] = ErrorsRepresenter } | ||
step Model( Contact , :find ) | ||
step Contract::Build(constant: Api::V1::Contacts::Contract::Create) | ||
step Contract::Validate() | ||
step Contract::Persist() | ||
end |
13 changes: 13 additions & 0 deletions
13
app/concepts/api/v1/contacts/representer/address_module.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
module Api::V1::Contacts::Representer | ||
module AddressModule | ||
include Representable::JSON | ||
include Reform::Form::Module | ||
|
||
property :id, writeable: false | ||
property :street_address | ||
property :neighborhood | ||
property :city | ||
property :state | ||
property :country | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
module Api::V1::Contacts::Representer | ||
module ContactModule | ||
include Reform::Form::Module | ||
|
||
property :id, writeable: false | ||
property :first_name | ||
property :last_name | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
module Api::V1::Contacts::Representer | ||
module Create | ||
include Representable::JSON | ||
include ContactModule | ||
|
||
property :address, populate_if_empty: Address do | ||
include AddressModule | ||
end | ||
|
||
collection :telephones, populate_if_empty: Telephone do | ||
include TelephoneModule | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
module Api::V1::Contacts::Representer | ||
module Index | ||
include Representable::JSON::Collection | ||
|
||
items class: Contact do | ||
include Representable::JSON | ||
include ContactModule | ||
|
||
property :address, populate_if_empty: Address do | ||
include AddressModule | ||
end | ||
|
||
collection :telephones, populate_if_empty: Telephone do | ||
include TelephoneModule | ||
end | ||
end | ||
end | ||
end |
10 changes: 10 additions & 0 deletions
10
app/concepts/api/v1/contacts/representer/telephone_module.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
module Api::V1::Contacts::Representer | ||
module TelephoneModule | ||
include Representable::JSON | ||
include Reform::Form::Module | ||
|
||
property :id, writeable: false | ||
property :number | ||
property :label | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
class Api::V1::ContactsController < ApiController | ||
def index | ||
endpoint Api::V1::Contacts::Index | ||
end | ||
|
||
def create | ||
endpoint Api::V1::Contacts::Create | ||
end | ||
|
||
def show | ||
endpoint Api::V1::Contacts::Show | ||
end | ||
|
||
def update | ||
endpoint Api::V1::Contacts::Update | ||
end | ||
|
||
def destroy | ||
endpoint Api::V1::Contacts::Destroy | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
require 'trailblazer/operation' | ||
|
||
class ApiController < ActionController::Base | ||
protect_from_forgery with: :null_session | ||
|
||
protected | ||
|
||
def default_handler | ||
->(m) do | ||
m.destroyed { |result| head :no_content } | ||
# m.present { |result| render json: result[:model].extend(result['representer.render.class']).to_json } | ||
m.created { |result| render json: result[:model].extend(result['representer.render.class']).to_json, status: :created } | ||
m.success { |result| render json: result[:model].extend(result['representer.render.class']).to_json } | ||
m.invalid { |result| render json: result["representer.errors.class"].new(result["result.contract.default"].errors.messages).to_json, status: :unprocessable_entity } | ||
m.not_found { |result| render json: { error: result[:error] }, status: :not_found } | ||
# m.unauthenticated { |result| render json: result[:model].extend(result['representer.render.class']).to_json } | ||
end | ||
end | ||
|
||
def endpoint(operation_class, options={}, &block) | ||
Api::Endpoint.(operation_class, default_handler, {params: params.to_unsafe_h}, &block) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
module Api | ||
class Endpoint < Trailblazer::Endpoint | ||
# this is totally WIP as we need to find best practices. | ||
# also, i want this to be easily extendable. | ||
Matcher = Dry::Matcher.new( | ||
destroyed: Dry::Matcher::Case.new( # DISCUSS: the "present" flag needs some discussion. | ||
match: ->(result) { result.success? && result[:model].try(:destroyed?) }, | ||
resolve: ->(result) { result }), | ||
# present: Dry::Matcher::Case.new( # DISCUSS: the "present" flag needs some discussion. | ||
# match: ->(result) { result.success? && result["present"] }, | ||
# resolve: ->(result) { result }), | ||
success: Dry::Matcher::Case.new( | ||
match: ->(result) { result.success? }, | ||
resolve: ->(result) { result }), | ||
created: Dry::Matcher::Case.new( | ||
match: ->(result) { result.success? && result["model.action"] == :new }, # the "model.action" doesn't mean you need Model. | ||
resolve: ->(result) { result }), | ||
not_found: Dry::Matcher::Case.new( | ||
match: ->(result) { result.failure? && result[:model].nil? }, | ||
resolve: ->(result) { result }), | ||
# TODO: we could add unauthorized here. | ||
# unauthenticated: Dry::Matcher::Case.new( | ||
# match: ->(result) { result.failure? }, # FIXME: we might need a &. here ;) | ||
# resolve: ->(result) { result }), | ||
invalid: Dry::Matcher::Case.new( | ||
match: ->(result) { result.failure? && result["result.contract.default"] && result["result.contract.default"].failure? }, | ||
resolve: ->(result) { result }) | ||
) | ||
|
||
def matcher | ||
Api::Endpoint::Matcher | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
module Api::V1::ContactsHelper | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
require 'representable/json/hash' | ||
|
||
class ErrorsRepresenter < Representable::Decorator | ||
include Representable::JSON::Hash | ||
self.representation_wrap = :errors | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# Use reform indexed errors | ||
Reform::Contract::Result::Errors.index_errors = true | ||
|
||
# Set errors wrapper in initialization | ||
ErrorsRepresenter.representation_wrap = :errors |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.