GithubHelp home page GithubHelp logo

gousto-test's Introduction

Installation

The project contains standard installation of Laravel, however you'll need to install / update dependancies via composer:

composer install && composer update

As the installation runs on SQLite database contained within a file, make sure that your Apache supports it. You'll also need to create the file itself by running

Linux

touch database\database.sqlite

or

Windows

copy nul database\database.sqlite

Run migrations to populate the database structure, by running:

php artisan migrate

Run seeder to populate the database with data, by running:

php artisan db:seed

Description

With the data provided I've decided to split the structure into a number of objects:

  • Recipe
  • RecipeBoxType (given recipe can be included in different box types)
  • RecipeDietType (given recipe can be classified as of multiple diet types)
  • RecipeCuisine (given recipe can belong to multiple cuisines)
  • RecipeEquipment (given recipe might require multiple equipments to create)
  • Slug (a url under which given content is reachable, not restricted to Recipes)
  • Review (a review of given content)

To fulfill the criteria of the test, I've created an API with a number of endpoints, each tasked with performing different operations:

  • GET:/recipes - displays paginated view of all recipes; can be filtered by passing ?recipe_cuisine_id=x as parameter
  • GET:/recipes/[id] - displays view of one recipe, determined by id
  • POST:/recipes/[id]/rate - creates a rating of given recipe; rating attribute is required within POST body
  • POST:/recipes - creates a recipe; title and slug attributes are required within POST body; as Recipe <-> RecipeFoo relationships are one to many, RecipeFoo ids are passed within an array - e.g. to create a Recipe with both asian and italian cuisine one would pass {recipe_cuisine_id: [1,2]}
  • PUT:/recipes/[id] - updates a recipe; Recipe <-> RecipeFoo relationships are overridden with provided data - e.g. if given Recipe has {recipe_cuisine_id: [1]}, passing {recipe_cuisine_id: [2]} will replace existing attribute; missing attributes do not update - e.g. {title: 'foo', 'slug': 'bar'} updated with {title: 'xyz'} will result in {title: 'xyz', 'slug': 'bar'}
  • DELETE:/recipes/[id] - deletes a recipe

Other models also have limited CRUD endpoints; each models functionality is contained within a models Controller. To keep the naming conventions consistent I've introduced namespace, which is used to group functionalities of given model and is derived from class name (for the purpose of nice URLs, it's using kebab-case)

As Laravel grants the ability of loading models per route (/{foo}/, handled by FooController@store with signature public function store(Foo $foo)), but PHP prevents inheriting methods with different signature (for public function store(Foo $foo) inheriting from public function store(Bar $bar)) I couldn't abstract similar CRUD operations; I've decided however to create a Trait that will allow me to chain CRUD operations on controller classes - CrudApiControllerTrait e.g. both store(Foo $foo) and store(Bar $bar) will take advantage of Laravel model loading, while chaining through store method of Trait. As such, CRUD operations can now be applied to all models without code duplication. This approach also allows to take advantage of dependancy injection of Request classes, allowing for decoupling validations from operations.

I've decided to use two approaches to manage the store/update/delete operations on classes:

  • Service approach used for Recipe, where extended functionality is required (saving a Recipe requires saving a Slug and other objects)
  • Model approach used for RecipeBoxType, where extended functionality is not required (due to simplicity of model in question)

Still, if RecipeBoxType models functionality extends, it's easily enough to provide given functionality by creating a service that handles its operations. I've also decided to put in RecipeBoxType CRUD routes to explore if there're no issues with these parts of code.

Generally I've tried to use services wherever possible to take advantage of loose coupling and dependancy injection provided by Laravel.

For the JSON responses, I've decided to use Transformers that are bundled with Laravel, that allow customization, up to a single request (Transformer does allow to look at Request object and customize output dependant upon the headers); it can also be customized based upon user within given request.

I think the approaches I've used make the application easily extendable - adding management of other models should be as simple as:

  • creating routes
  • creating controller that uses CrudApiControllerTrait, with model extending Base class
  • creating service if extended functionality is required
  • if index/show output is required - creating transformer

gousto-test's People

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.