Consider the following User model
schema:
create_table "users", id: :serial, force: :cascade do |t|
t.string "fname"
t.string "lname"
end
Model:
class User < ApplicationRecord
attr_accessor :email # no column in database
end
Controller:
def user_params
params.require(:user).permit(:fname, :lname, :email)
end
I'm writing an API to which I'm sending a POST request to the users endpoint with the following keys/values:
{
"fname": "John",
"lname": "Doe",
"email": "email@email.com",
}
I would expect params[:user] to include the key :email as even though it is not a database column, it is defined as an attribute via the attr_accessor in the model.
However, the :email key is not nested within params[:user], and has to be accessed at the params level params[:email].
# POST /users { "fname": "John", "lname": "Doe", "email": "email@email.com" }
Processing by UsersController#create as JSON
Parameters: {"user"=>{"fname"=>John, "lname"=>"Doe"}, "email"=>"email@email.com"}
I believe ActionController#params_wrapper has something to do with this, but I don't understand the code enough to make it wrap attr_accessor defined attributes inside the user hash.
I need the :email key nested within params[:user]. Is there a way around this?
I believe ActionController#params_wrapper has something to do with this
Good hunch. However, you were too quick to jump into the code. Should have read the docs first :)
https://api.rubyonrails.org/classes/ActionController/ParamsWrapper.html
You can also specify the key in which the parameters should be wrapped to, and also the list of attributes it should wrap by using either :include or :exclude options like this:
class UsersController < ApplicationController wrap_parameters :person, include: [:username, :password] endOn Active Record models with no :include or :exclude option set, it will only wrap the parameters returned by the class method
attribute_names.