0

I guess my API knowledge is still limited because I could not figure this out.

I have an app that sits on React front end and Rails backend. If I want to delete one item at a time, I can do something like this:

function deleteSomething(somethingId){
  return fetch(`api/something/${somethingId}`, {
    method: 'DELETE'
  })
}

and in Rails controller, I do something like

  def destroy
    @something = Something.find(params[:id]).destroy
    head :no_content
  end

My routes look like this:

scope :api do
  resources :something, only: [:index, :show, :create, :update, :destroy]
  ...

This time, I want to destroy multiple items at once. I found this SO post that talks about destroy_all; I tested it on my rails console and it worked like magic (isn't Rails itself magical?).

However, I could not figure out how to write fetch method or the routing.

  def destroy
    Something.destroy_all(:name => params[:name]) #if I want to destroy all Model with certain name
  end

How can I write the fetch method? I don't think I should include every single ID and iterate one by one, because that goes against why I wanted to use destroy_all in the first place.

function deleteSomehing(name){
  return fetch(`api/something/(what goes here?)`, {
    method: 'DELETE'
  })
}

Where should my fetch method be addressed/ routed to? What do I do with routing, should I create a new method inside controller for this, or can I stub it inside destroy?

EDIT: Here is what I have tried, but it did not work (error: Uncaught (in promise) SyntaxError: Unexpected end of JSON input)

function customDeleteName(name){
  return fetch(`api/something/delete_by_name`, {
    method: 'POST',
    headers: {
      'Content-Tye': 'application/json'
    },
    body: JSON.stringify({
      name: name
    })
  }).then((response) => response.json())
}

Inside routes - api scope:

scope :api do
      post '/something/delete_by_name' => 'something#delete_by_name'

Inside controller:

  def delete_by_name
    Something.destroy_all(:name => params[:name])
  end

EDIT2:

#routes
scope :api do
  delete `/something/delete_by_name/:name`, to: 'something#delete_by_name'

#controller
def delete_by_name
  Something.destroy_all(:name => params[:name])
  head :no_content
end


## JS side ##
#fetch:
function deleteSomething(name){
  return fetch(`api/something/delete_by_name/${name}`, {
    method: 'DELETE'
  })
}

Error:

ActionController::RoutingError (No route matches [DELETE] "/api/something/delete_by_name/somename"):
Iggy
  • 5,129
  • 12
  • 53
  • 87

2 Answers2

2

I think I would create a specific method/action for it on the controller. Given the model name, you can do:

"something".capitalize.constantize.destroy_all

If something has 2 names you'll need to capitalize it correctly before calling constantize on it.

scope :api do
   ...
   delete 'your/beautiful/route/:name', to: 'wherewild#thingsare'

wherewild_controller.rb

def thingsare
  #do magic rails
end

Now, you'll have a problem if you choose the same route path as you're using for the current delete, so better choose another one.

m3characters
  • 2,240
  • 2
  • 14
  • 18
  • Thanks, Micael! Additionally, if I created my own custom method, how can I invoke it on my routes and fetch? Do I send a "DELETE" method using fetch or should I use POST? – Iggy Jul 20 '17 at 20:29
  • @Iggy I never used "scope" so not really sure, you can always write the full route itself outside of the `scope block` or search how to add custom routes to `scope blocks` – m3characters Jul 20 '17 at 21:05
0

Figured out how to do it. @Micael's answer, although didn't solve it exactly, led me to the right direction. Big thanks to him!

I did a POST method onto the custom method/ route, and it worked:

#controller
   def delete_by_name
     Something.destroy_all(:name => params[:name])
     head :no_content
   end

#routes: 
  post '/delete_latest_name' => 'something#delete_by_name'

#JS#
  function deleteSomething(name){
    return fetch(`delete_latest_name`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        name: name
      })
    });
  }
Iggy
  • 5,129
  • 12
  • 53
  • 87