Issue with Devise resource_name when two route poi

2019-07-10 04:28发布

问题:

I have two route for my api v1 and v2 pointing to the same Devise model with the below routes:

scope :api do
  namespace :v1 do
    devise_for :users, :controllers => {:registrations => "devise/v1/users_registrations",
                                      :sessions => "devise/v1/users_sessions",
                                      :passwords => "devise/v1/users_passwords"}
  end
end

scope :api do
  namespace :v2 do
    devise_for :users, :controllers => {:registrations => "devise/v2/users_registrations",
                                      :sessions => "devise/v2/users_sessions",
                                      :passwords => "devise/v2/users_passwords"}
  end
end

My problem is when a request is sent to either one of these API's the Devise resource_name is either 'v1_user' or 'v2_user', but the parameters sent in have the values needed in params['user'].

I get this information from the Devise helpers.rb devise_parameter_sanitizer method. When Devise::ParameterSanitizer.new(resource_class, resource_name, params) params looks like below:

result = {ActionController::Parameters} ActionController::Parameters (4 elements)
'user' = {ActionController::Parameters} ActionController::Parameters (16 elements)
 'email' = "test@kemsoft.co"
 'password' = "qwertyuiop"
 'first_name' = "test"
 'last_name' = "testtest"
 'ship_street_address' = "1 main st"
 'ship_city' = "rome"
 'ship_state' = "TX"
 'ship_zip_code' = "12345"
 'dealer_number' = "1234567890"
 'business_name' = "ABC Pumps"
 'bus_street_address' = "121 West Ave"
 'bus_city' = "San Antonio"
 'bus_state' = "NY"
 'bus_zip_code' = "73412"
 'distributor_id' = "1"
 'additional_distributor_id' = "1"
'controller' = "devise/v1/users_registrations"
'action' = "create"
'format' = "json"

Not sure if this will be helpful information, but here is the devise_mapper:

result = {Devise::Mapping} #<Devise::Mapping:0x007fc7a2c8d950>
@class_name = "User"
@controllers = Hash (3 elements)
@failure_app = {Class} Devise::FailureApp
@format = nil
@klass = {Devise::Getter} #<Devise::Getter:0x007fc7a2c8d338>
@modules = Array (7 elements)
@path = "users"
@path_names = Hash (8 elements)
  registration => 
  new => new
  edit => edit
  sign_in => sign_in
  sign_out => sign_out
  password => password
  sign_up => sign_up
  cancel => cancel
@path_prefix = "/api/v1"
@router_name = nil
@routes = Array (3 elements)
  [0] = {Symbol} session
  [1] = {Symbol} password
  [2] = {Symbol} registration
@scoped_path = "v1/users"
@sign_out_via = {Symbol} delete
@singular = {Symbol} v1_user
@strategies = Array (2 elements)
  [0] = {Symbol} rememberable
  [1] = {Symbol} database_authenticatable
@used_helpers = Array (3 elements)
  [0] = {Symbol} session
  [1] = {Symbol} password
  [2] = {Symbol} registration
@used_routes = Array (3 elements)
  [0] = {Symbol} session
  [1] = {Symbol} password
  [2] = {Symbol} registration

回答1:

I did end up coming up with a solution, but it's not one I like all that much. I'm still open to other suggestion so I'm not going to mark this as the accepted answer, but it atleast got the job done.

Basically in my devise controllers I added a before_filter that added the expected parameter to the request.parameters and local params. It's pretty simple, but feels really hacky. Of course I've unit tested the hell out of it incase changes break it in the future.

before_filter :sanitize_params

def sanitize_params
  request.parameters[:v2_user] = params[:user] unless params[:user].nil?
  params[:v2_user] = params[:user] unless params[:user].nil?
end