es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿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?

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Basado en el código proporcionado, parece que el atributo :email está definido en el modelo User usando attr_accessor, pero no está incluido en el esquema de la base de datos. Por lo tanto, cuando la API recibe la solicitud, el hash params[: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 hash params porque no se reconoce como parte del modelo User.

    Una forma de manejar esto es modificar el método user_params en el controlador para incluir explícitamente el atributo :email:

    def user_params
      params.require(:user).permit(:fname, :lname).merge(email: params[:email])
    end
    

    Esto fusionará el atributo :email en el hash user_params y asegurará que se incluya al crear o actualizar un usuario. Ten en cuenta que esto asume que el parámetro email está presente en la solicitud, de lo contrario, generará un error.

    Otra alternativa es definir el atributo :email como un atributo virtual en el modelo User usando attribute en lugar de attr_accessor. Esto asegurará que se reconozca como parte del modelo User y se incluya en el hash params[:user]:

    class User < ApplicationRecord
      attribute :email, :string
    end
    

    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.

Comments are closed.