2010-10-15 7 views
65

He utilizado técnicas RESTful para generar un modelo (de hecho, estoy usando Devise gem, que hace eso por mí), y he agregado nuevos campos llamados first_name y last_name para el modelo. La migración fue bien. Agregué attr_accessor: first_name,: last_name al modelo y esperaba que simplemente funcionara. Pero cuando trato de asignar en masa nuevas instancias con Doctor.create ({: first_name => "MyName"}) etc., recibo errores que dicen que no puedo asignar en masa los atributos protegidos."ADVERTENCIA: No se puede asignar en masa los atributos protegidos"

Pensé que el objetivo de usar attr_accessor era evitar la protección de los campos de un modelo. ¿Puedes ayudarme a entender este mensaje?

Edición: oh, y por cierto los registros tampoco se crean. Pensé que deberían ser, ya que esto es solo una advertencia, pero no están en la base de datos.

Edit2: aquí está mi modelo

class Doctor < User 
    has_many :patients 
    has_many :prescriptions, :through=> :patients 

    validates_presence_of :invitations, :on => :create, :message => "can't be blank" 

    attr_accessor :invitations 
end 

y el esquema, que no tiene el nombre apellido y apellidos, ya que se crean en la tabla de usuarios, que es el antepasado de los médicos. Usé herencia de mesa única.

create_table :doctors do |t| 
    t.integer :invitations 

    t.timestamps 
end 

y esto es la migración de cambiar la tabla de usuarios

add_column :users, :first_name, :string 
add_column :users, :last_name, :string 
add_column :users, :type, :string 

EDIT: Aquí está el archivo semilla. No incluyo el método truncate_db_table, pero funciona.

%w{doctors patients}.each do |m| 
    truncate_db_table(m) 
end 

Doctor.create(:invitations=>5, :email=>"[email protected]", :first_name=>"Name", :last_name=>"LastName") 
Patient.create(:doctor_id=>1, :gender=>"male", :date_of_birth=>"1991-02-24") 
+0

Todavía no soy muy inteligente en Rails 4, pero creo que esta pregunta es una pregunta de Rails 3. ¡La configuración predeterminada de hardcoded en 'config/application.rb' en Rails 4 está en blanco! –

+0

http://apidock.com/rails/ActiveRecord/Base/attr_accessible/class – shilovk

Respuesta

139

No confunda attr_accessor con attr_accessible. Accessor está integrado en Ruby y define un método getter - model_instance.foo # returns something - y un método setter - model_instance.foo = 'bar'.

Accesible está definido por Rails y hace que el atributo se pueda asignar a la masa (hace lo contrario de attr_protected).

Si first_name es un campo en la tabla de la base de datos de su modelo, entonces Rails ya ha definido getters y setters para ese atributo. Todo lo que necesita hacer es agregar attr_accessible :first_name.

+0

Ahora recibo un error de "atributo desconocido" en las invitaciones cuando rastrillo el archivo inicial. Sin embargo, sé que tengo este campo en la base de datos; está en el archivo de migración ... – picardo

+0

Está en el archivo de migración, pero ¿ejecutó las migraciones? Publica tu archivo de semillas. –

+0

¿Has actualizado las otras cosas? Todavía tiene attr_accessor en su modelo aunque eso esté mal. –

1

No utilice attr_accessor aquí. ActiveRecord los crea automáticamente en el modelo. Además, ActiveRecord no creará un registro si se produce un error de validación o asignación masiva.

EDITAR: No necesita una tabla de médicos, necesita una tabla de usuarios con una columna de tipo para manejar Rails Single Table Inheritance. Las invitaciones estarán en la tabla de usuarios. Ah, veo en tu ejemplo de código agregado que tienes que escribir en los usuarios. Deshágase de la mesa de médicos, envíe invitaciones a los usuarios y creo que debería estar bien. También deshazte del attr_accessor. Innecesario.

Tenga en cuenta que los raíles STI usan la misma tabla para todas las clases y subclases de un modelo en particular. Todos sus registros médicos serán filas en la tabla de usuarios con un tipo de 'doctor'

EDITAR: Además, ¿está seguro de que solo desea validar la presencia de invitaciones en la creación y no las actualizaciones?

+0

Sin embargo, cuando no lo uso, Rails me dice "método no encontrado" ya que estoy rastrillando el archivo inicial. ¿Qué debería hacer en ese caso? – picardo

+0

¿Puedes publicar el código del modelo y la tarea de rake? También la migración que creó el modelo. Asegúrese de que esas columnas se creen en db. –

11

piratear su aplicación en conjunto de una manera insegura totalmente inadecuada para el modo de producción:

Ir a/config/aplicación.rb Desplácese hacia abajo hacia el final donde encontrará

{config.active_record.whitelist_attributes = true} 

Establézcalo en falso.

EDITAR/BTW (después de 4 meses de trabajo rubí intenso, incluyendo un taller de 11 semanas): DHH cree que, para noobies (sus palabras), "en marcha y funcionando" es más importante que "muy seguro" .

SE ACONSEJA: Aunque esta respuesta (la primera en stackoverflow, creo) es ahora en +6, ha sido tan bajo como -4 en su historia, lo que significa que muchos desarrolladores de rails experimentados se sintieron muy apasionado por no que desee que haga esto.

ACTUALIZACIÓN: 3 años más tarde, otra manera de hacer esto - de nuevo, no es seguro, pero es mejor que la solución anterior, probablemente porque hay que hacerlo para cada modelo

class ModelName < ActiveRecord::Base 
    column_names.each do |col| 
    attr_accessible col.to_sym 
    end 
    ... 
end 
+32

Eso es realmente un mal consejo incluso con la advertencia de "codificación temprana". ¿Cuándo los desarrolladores alguna vez tienen la oportunidad de volver atrás y refactorizar toda su aplicación? Hazlo bien desde el principio. – toxaq

+4

"tenga en cuenta que este es un agujero de seguridad pero puede manejarlo más tarde" ¿Cuándo planeaba enfrentarlo? Más tarde, cuando está en producción? Acabo de agregar "¿cuál es su opinión sobre attr_accessible?" a mi lista de preguntas de la entrevista. – toxaq

+0

¿Puedo sugerir una edición para aclarar su respuesta? Desde su publicación, no está del todo claro que el valor predeterminado sea la manera más segura, y al cambiarlo a falso se obtiene un acceso fácil a los atributos del modelo, pero se abre el agujero de seguridad. – Excalibur

0

Añadir a su attr_accessible : variable1, variable2 archivo de ruta de tabla.

0

De acuerdo con la respuesta de @Robert Speicher Pero recomiendo encarecidamente que debe utilizar Strong parameter en lugar de attr_accessible para protegerse de la asignación masiva.

¡Salud!

Cuestiones relacionadas