2010-10-28 10 views
9

Tengo una tabla heredada que mi aplicación de rieles comparte con otra aplicación. Tiene una columna llamada "clase". La primera vez que hago referencia a cualquier atributo en ese modelo, aparece un error. Las referencias posteriores a los atributos funcionan. ¿Existe una buena solución para esto, o debería simplemente modificar la otra aplicación que usa esta tabla (ugh)?Tabla heredada con columna denominada "clase" en Rails

>> Member::Ssg.find(:first) 
=> #<Member::Ssg ssg_key: #<BigDecimal:10b169688,'0.253E3',4(8)>, org_id: 2, academic_year: 2006, class: true, next_due_date: "2011-06-01", submitted_date: "2006-02-13", notes: nil, owner_id: "1"> 
>> Member::Ssg.find(:first).notes 
NoMethodError: undefined method `generated_methods' for true:TrueClass 
     from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/attribute_methods.rb:247:in `method_missing' 
     from (irb):2 
>> Member::Ssg.find(:first).notes 
=> nil 

SOLUCIÓN: Fui con una combinación de la solución Bellmyer y añadiendo el siguiente código para mi modelo

class << self 
    def instance_method_already_implemented?(method_name) 
    return true if method_name == 'class' 
    super 
    end 
end 
+0

sólo quiero decir que su solución actualizada funcionó muy bien. ¡Gracias! –

+0

@JustinHoldsclaw, ¿lo probaste en Rails 4 o 5? –

+0

@ MahmoudM.Abdel-Fattah esto fue en Rails 4.2 –

Respuesta

9

NOTA: Por favor ver la solución actualizada al final de esta respuesta. Dejando la solución obsoleta original por razones históricas.

Esto ha aparecido con la suficiente frecuencia (los nombres de columnas heredadas que interfieren con ruby ​​/ rails) que podría hacer un complemento de esto. Sin embargo, aquí es cómo puedes solucionarlo de inmediato. Crear este archivo en su aplicación:

# lib/bellmyer/create_alias.rb 
module Bellmyer 
    module CreateAlias 
    def self.included(base) 
     base.extend CreateAliasMethods 
    end 

    module CreateAliasMethods 
     def create_alias old_name, new_name 
     define_method new_name.to_s do 
      self.read_attribute old_name.to_s 
     end 

     define_method new_name.to_s + "=" do |value| 
      self.write_attribute old_name.to_s, value 
     end 
     end 
    end 
    end 
end 

Y ahora, en su modelo:

class Member < ActiveRecord::Base 
    include Bellmyer::CreateAlias 
    create_alias 'class', 'class_name' 
end 

El primer parámetro a create_alias es el antiguo nombre del método, y el segundo parámetro es el nuevo nombre que desea llámalo, eso no interferirá con los rieles. Básicamente utiliza los métodos read_attribute y write_attribute para interactuar con la columna en lugar de los métodos ruby ​​que se definen por ActiveRecord. Sólo asegúrese de usar el nuevo nombre para el campo en todas partes, así:

member.class_name = 'helper' 

Esto funciona con Ruby 1.8, pero no he probado con el rubí 1.9 todavía. ¡Espero que esto ayude!

ACTUALIZACIÓN: He encontrado una mejor solución que funciona en Rails 3, la joya safe_attributes. Escribí una publicación en el blog que explica cómo usarla, con ejemplos de fragmentos de código y una aplicación de muestra completa que puedes descargar desde github y jugar con ella. Aquí está el enlace:

Legacy Database Column Names in Rails 3

+1

Esto no acaba de hacer el truco. Me permite hacer referencia al valor de la columna de la clase, pero todavía aparece el error NoMethodError: método no definido 'generated_methods 'para verdadero: TrueClass de /Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/ active_record/attribute_methods.rb: 247: en 'method_missing ' de (irb): 2 – Anna

+0

He actualizado mi respuesta con una solución de trabajo. –

Cuestiones relacionadas