Search code examples
rubyactiverecordstrong-parametersgrape-apigoliath

How to achieve strong parameter protection without Rails?


I am developing a boilerplate web application with Goliath + Grape + Active Record 4.2 + Active Record Migrations. Here is my migration file

# db/migrate/20150519063210_create_albums.rb
class CreateAlbums < ActiveRecord::Migration
  def change
    create_table :albums do |t|
      t.string :name
      t.string :artist
      t.string :genre
      t.date :published_at
    end
  end
end

And my model

# app/models/Album
class Album < ActiveRecord::Base
end

And the Grape API

class ApiV1 < Grape::API
  version 'v1', using: :path
  format :json

  resource 'albums' do
    get '/' do
      Album.all
    end

    post '/' do
      Album.create(params[:album])  # <-- raises ActiveModel::ForbiddenAttributesError
    end
  end
end

When I call POST /v1/albums/ with some parameters, the application always raises ActiveModel::ForbiddenAttributesError. It seem that ActiveRecord wants ActionController::Parameters to be the arguments, but Grape gives it Hashie::Mash.

I've tried implementing a simple Rack middleware to convert env['params'] from a Hash to a ActionController::Parameters and using it after Goliath::Rack::Params, but Grape just sanitizes it out when the helper method params is called. I also tried implementing and using a Grape middleware to do the same thing and got the same result.

Is there any solution on this or I just have to down grade to ActiveRecord 3?


Solution

  • You could create a helper to generate an instance of ActionController::Parameters with your parameters:

    require 'action_controller/metal/strong_parameters' 
    
    class ApiV1 < Grape::API
      version 'v1', using: :path
      format :json
    
      helpers do
        def albums_params
          ActionController::Parameters.new(params).require(:album).permit(:attr1, :attr2)
        end
      end
    
      resource 'albums' do
        get '/' do
          Album.all
        end
    
        post '/' do
          Album.create(albums_params)
        end
      end
    end
    

    Or you can use the hashie-forbidden_attributes gem.