¿Rails attr_accessor define atributos fuera de strong params hash en el controlador?
Considere el siguiente modelo de User
Esquema:
create_table "users", id: :serial, force: :cascade do |t|
t.string "fname"
t.string "lname"
end
Modelo:
class User < ApplicationRecord
attr_accessor :email # no hay columna en la base de datos
end
Controlador:
def user_params
params.require(:user).permit(:fname, :lname, :email)
end
Estoy escribiendo una API a la cual envío una solicitud POST al endpoint de users
con las siguientes claves/valores:
{
"fname": "John",
"lname": "Doe",
"email": "email@email.com"
}
Esperaría que params[:user]
incluya la clave :email
, ya que aunque no es una columna de la base de datos, está definida como un atributo a través de attr_accessor
en el modelo.
Sin embargo, la clave :email
no está anidada dentro de params[:user]
y debe ser accedida a nivel de params
a través de 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"}
Creo que ActionController#params_wrapper
tiene algo que ver con esto, pero no entiendo lo suficiente el código como para hacer que envuelva los atributos definidos por attr_accessor
dentro del hash user
.
Necesito que la clave :email
esté anidada dentro de params[:user]
. ¿Hay alguna manera de solucionar esto?
davy.ai
Basado en el código proporcionado, parece que el atributo
:email
está definido en el modeloUser
usandoattr_accessor
, pero no está incluido en el esquema de la base de datos. Por lo tanto, cuando la API recibe la solicitud, el hashparams[:user]
solo incluye los atributos que están definidos en el esquema de la tabla (es decir,:fname
y:lname
). El atributo:email
termina como una clave separada en el hashparams
porque no se reconoce como parte del modeloUser
.Una forma de manejar esto es modificar el método
user_params
en el controlador para incluir explícitamente el atributo:email
:Esto fusionará el atributo
:email
en el hashuser_params
y asegurará que se incluya al crear o actualizar un usuario. Ten en cuenta que esto asume que el parámetroemail
está presente en la solicitud, de lo contrario, generará un error.Otra alternativa es definir el atributo
:email
como un atributo virtual en el modeloUser
usandoattribute
en lugar deattr_accessor
. Esto asegurará que se reconozca como parte del modeloUser
y se incluya en el hashparams[:user]
:Con esta modificación, el hash
params[:user]
debería incluir el atributo:email
incluso si no está presente en el esquema de la base de datos.