Home > Back-end >  Create a rails api with another attribute as an end point
Create a rails api with another attribute as an end point

Time:08-21

I am creating an API with ruby on rails. I have got the basis of it done by following https://levelup.gitconnected.com/7-steps-to-create-an-api-in-rails-2f984c7c4286

but instead of Forests and trails, I am using restaurants and Comments as my models. Restaurants has many comments and comments has one restaurant - no user model for this.

But the show inside restaurants_controller.rb is this instead: (no controller for comments)

  def show
    @restaurant = Restaurant.find(params[:id])
    @comments = @restaurant.comments
    render json: @comments
  end

Right now the link I have been testing is http://localhost:3000/restaurants/1

which creates a JSON with all comments for restaurant 1 (with separate IDs for each comment).

[
    {
        "id": 1,
        "restaurant_id": 1,
        "comment": "good.",
         "age": 28,
        "created_at": "2022-08-20T10:00:00.000Z",
        "updated_at": "2022-08-20T10:00:00.000Z"
    },
    {
        "id": 2,
        "restaurant_id": 1,
        "comment": "very good.",
         "age": 25,
        "created_at": "2022-08-20T12:30:00.000Z",
        "updated_at": "2022-08-20T12:30:00.000Z"
    }
]

What I want to do now is further search through that API by another attribute. Comments has another attribute called age that I would like to search through.

So now I want this: http://localhost:3000/restaurants/1/28

Which would show only the comments for restaurant 1 AND only by those aged 28.

intended output:

[
    {
        "id": 1,
        "restaurant_id": 1,
        "comment": "good.",
         "age": 28,
        "created_at": "2022-08-20T10:00:00.000Z",
        "updated_at": "2022-08-20T10:00:00.000Z"
    }
]

I am new to creating API's. Hope I've got the lingo correct here. Is this possible to do? I have not been able to find anything like this anywhere - probably searching for wrong key words

I did think about using another route? But that would then lead to something like http://localhost:3000/api/v1/restaurants/1/comments/28 which isn't want I want!

routes.rb

Rails.application.routes.draw do
   resources :restaurants, only: [:index, :show, :create, :update]
end

CodePudding user response:

It could be done by configuring your routes, but this approach is brittle. What if next you wanted to get comments filtered by some other attribute (e.g. comment=~/good/.

I think a better approach is to add a query string to carry the age query. The routes are not affected. So the http request would be something like:

http://localhost:3000/restaurant/1/comments?age=lt28

You would then decode the lt28 as "less than 28" on the server

or define a scope max_age on the comments model and use a query like this:

http://localhost:3000/restaurant/1/comments?max_age=28

[update] after some more thought, I wanted to mention that the approach you're considering is not really conformant with the REST paradigm. Of course, REST is not "the law", and you can choose to ignore it, but with consideration.

  • Related