Giter Site home page Giter Site logo

madeindjs / api_on_rails Goto Github PK

View Code? Open in Web Editor NEW
362.0 19.0 121.0 9.42 MB

Learn best practices to build an API using Ruby on Rails 5/6

Home Page: https://leanpub.com/apionrails6

License: MIT License

Ruby 100.00%
rails book api jwt-authentication ruby asciidoctor api-rest best-practices

api_on_rails's Introduction

Hi there 👋

My statistics

api_on_rails's People

Contributors

airdry avatar aleksandrilyin avatar bit4bit avatar crazyoptimist avatar cuilei5205189 avatar dependabot[bot] avatar dianedelallee avatar forerunnerg34 avatar franklinjosmell avatar itsjustkevin avatar j0eii avatar kerolloz avatar lex111 avatar luizbinario avatar madeindjs avatar notapatch avatar oscartzgz avatar promisepreston avatar tacataca avatar tavofigse avatar zovube avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

api_on_rails's Issues

Chapter 2 API Versioning

Hi madeindjs

Thanks for looking at this book there are very little covering Rails APIs. I couldn't work out this bit on Chapter 2:

Api versioning

At this point we should have a nice routes mapping using a namespace. Your routes.rb file should look like this:

Listing 5. config/routes.rb

Rails.application.routes.draw do
  # Api definition
  namespace :api, defaults: { format: :json }, path: '/'  do     <=== ?
    # We are going to list our resources here
  end
end

The only problem is that the path: '/' has just appeared after the final commit and it's not clear where it came from as it was not in any of the previous listings.

Devise install error in chapter 3

Running rails g devise:install gives this error

/home/tac/.rvm/gems/ruby-2.6.0/gems/bootsnap-1.3.2/lib/bootsnap/load_path_cache/core_ext/active_support.rb:74:in 'block in load_missing_constant': uninitialized constant ApiConstraints (NameError)

Also the git clone link given at the start of chapter 3 does not seem to be valid.

How to access api in postman or browser ?

Hi, i understand you using prax/pow but if i dont want to use them and instead try out the api on postman/browser using localhost:3000 , then what would be the URI/URL for that ? Thanks in advance.

[Rails6:EN] Subdomain constraint not working

Hi, first of all thanks for working on updating this tutorial.

I have been trying to follow the rails 6 version and on chapter 3, when testing via the api for the first time via curl, I noticed 2 issues:

  • The path is incorrect (if using the constraint), its listed as /api/v1/users/1 while it should be /users/1
  • The subdomain constraint isn't working because doing something like curl http://api.localhost:3000/users/1 is invalid (unless you define api.localhost on your hosts file)

What I would suggest to be able to use the subdomain constraint on local development is:

  1. Use lvh.me which resolves itself plus any subdomain to localhost (without user requiring to change anything on their system). For rails 6, you would just need to add config.hosts << "api.lvh.me" somewhere in your development.rb environment file.
    With this you can run curl http://api.lvh.me:3000/users/1
  2. Alternatively add a section on editing the system hosts file.

Chapter 4 Logged user

Logged user
So we implemented the following logic: API returns the authentication token to the client if credentials are correct.
We will now implement the following logic: we’ll find the corresponding user of an authentication token given into the HTTP header. We’ll need to do so each time this client requests a protected page.

My question is: Do you mean "protected page"? Protected pages make sense in a standard Rails application but I'm confused about how an API app has pages. I was wondering if it might be better described as:

We’ll need to do so each time a client request requires permission.

Otherwise authorization?

N+1 Queries fix is wrong - include should be include*s*

The fix in the code is incorrect it should be include_s_ and not include. I can't do a PR because I'm not sure how you want to fix it.

The wrong code is first introduced in Prevention of N + 1 requests. Listing 152. app/controllers/api/v1/products_controller.rb

ApplicationController
  # ...
  def index
    @products = Product.includes(:user)
                       .page(current_page)
                       .per(per_page)
                       .search(params)

    options = get_links_serializer_options('api_v1_products_path', @products)
    # needs an s \/
    options[:include] = [:user]

    render json: ProductSerializer.new(@products, options).serializable_hash.to_json
  end
  # ...
end

The book code demonstrates that with the change in Listing 152 there is still an N+1 error in products.

GET /api/v1/products
USE eager loading detected
  Product => [:user]
  Add to your finder: :includes => [:user]
He even tells us how to correct it:
> Add to your search engine
includes ⇒ [: user]

Then there's a final listing 154 that copies the Listing 152, along with the mistake.

I can't see a way of changing just the code. I think some writing must be changed as well.

Chapter 3: Build users - namespace nesting in book different from my generated code

Under: Chapter 3: Build users Listing 11

The book shows UsersControllerTest with no namespace nesting:

Listing 11. test/controllers/api/v1/users_controller_test.rb
#    v------------- THIS BIT 
class UsersControllerTest < ActionDispatch::IntegrationTest
  ...
  ... None generated code. Entered by you.
  ...
end

When I do the generation rails g controller api::v1::users - I get additional namespace of Api::V1 generated:

require 'test_helper'
        V----------- THIS BIT
class Api::V1::UsersControllerTest < ActionDispatch::IntegrationTest
  # test "the truth" do
  #   assert true
  # end
end

However, I did get the same namespace as Listing 12 for the users_controller.rb.

# app/controllers/api/v1/users_controllers.rb

class Api::V1::UsersController < ApplicationController
end

Note: If you make a change then Listing 11 then Listing 14 will need to be changed also.

Last link on Chapter 2 goes to the wrong code

The link on 'here'

I’m not covering those in this book, since we are trying to learn how to actually implement this kind of functionality, but it is good to know though. By the way the code up to this point is here.

I believe this is the link: madeindjs/market_place_api@1248737

Confusing as it's rspec configuration when this book is covering minitest.

asciidoctor versioning different between Gem and lockfile

I'm not sure how important the move from 1.5 to 2.0 so I haven't put a pull request in. Before you can run the rake build the user has to fix this issue.

# Gemfile
gem 'asciidoctor', '~> 1.5'
# Gemfile.lock
asciidoctor (2.0.10)

No chapter headings in the book

There are no chapter headings in the book. It makes it difficult to find where you are in the book.
I'm using EPUB but checking PDF it looks missing as well..

Broken link

There is a broken link : "Schema of links betweens models".

Chapter 6 Listing 88/89 tests ordering without being ordered

I'm going through the book again... :-}

In listing 88 you're testing for a sort order but in listing 89 it's a WHERE clause without any ordering. SQL makes no guarantees in this situation, if it passes that's luck. You need some ordering or remove the test.

Listing 88. test/models/product_test.rb

class ProductTest < ActiveSupport::TestCase
  # ...
  test 'should filter products by name and sort them' do
    assert_equal [products(:another_tv), products(:one)], Product.filter_by_title('tv').sort
  end
end

Listing 89. app/models/product.rb

class Product < ApplicationRecord
  # ...
  scope :filter_by_title, lambda { |keyword|
    where('lower(title) LIKE ?', "%#{keyword.downcase}%")
  }
end

Chapter 4 - autoload_path

Chapter 4 autoload

Listing 5. lib/json_web_token.rb
# ...
module MarketPlaceApi
  class Application < Rails::Application
    # ...
    config.autoload_paths << Rails.root.join('lib')
  end
end

I notice you're using autoload. I find the area confusing. My understanding is autoloading lib was not threadsafe which is a problem with Puma in production and the suggestion was you should stick lib into app :-| I couldn't bring myself to do that and went with the other suggestion of changing autoload to eager load, which autoloads in development and eager loads, no requests until code loaded, in production.

https://stackoverflow.com/questions/19773266/confusing-about-autoload-paths-vs-eager-load-paths-in-rails-4?noredirect=1&lq=1

Chapter 6 on Test sort products

test 'should sort product by most recent' do
# we will touch some products to update them
products(:two).touch
products(:one)

I implemented the test code and code on model but test fails becuase doesn't return products in expected order, also anyone can explain me what does those two last lines? I understand that the first line updates the datetime on "updated_at" atrribute, but second line, what does?

Chapter 2 config/routes.rb listing 4-6 changes

One of the confusing things in Chapter 2 is the block inside the namespace :api

Listing 4. config/routes.rb

Rails.application.routes.draw do
  namespace :api, defaults: { format: :json } do
    namespace :v1 do                   <= This guy
      # We are going to list our resources here
    end
  end
end

You then commit as "Set the routes constraints for the api". So far no problem. Then we see.

Listing 5. config/routes.rb

Rails.application.routes.draw do
  # Api definition
  namespace :api, defaults: { format: :json }  do
    # We are going to list our resources here           <= where's it gone?
  end
end

This is a bit confusing as the version namespace :v1 has disappeared. Maybe it's because it wasn't interesting? Maybe because it's a mistake? However, In Listing 6 we have namespace changed to scope.

Listing 6. config/routes.rb

Rails.application.routes.draw do
  # Api definition
  namespace :api, defaults: { format: :json }  do
    scope module: :v1 do            <= so we changed namespace to scope?
      # We are going to list our resources here
    end
  end
end

Is the progression from Listing 4 (adding an inner namespace), Listing 5 (missing it out again) and Listing 6 (inner scope module) deliberate? It's quite confusing to follow and not clear from the text why these changes happened.

Image to embed not found in chapter 02

When I run "rake build:pdf[6,en]" for generate the pdf version. I get:

asciidoctor: WARNING: image to embed not found or not readable: .../api_on_rails/rails6/en/img/img/data_model.png

This happened after merge the pull request #24

Serialize generator already adds attributes

In Chapter 6 - section Serialize Products. We use a generator like so:

rails generate serializer Product title price published

This automatically adds the attributes. However, in the text you are encouraged to add the, already created, attributes. As follows:

Suggested changes

$ rails generate serializer Product title price published
      create  app/serializers/product_serializer.rb

Now let’s add attributes to serialize the product:
Now check the generated product serializer:

Listing 75. app/serializers/product_serializer.rb
class ProductSerializer
  include JSONAPI::Serializer
  attributes :title, :price, :published
end

There you go. It’s no more complicated than that. Everything looks right. Let’s change our controller a little bit.

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.