2011-02-06 9 views
7

Tengo una base de datos heredada que estoy tratando de modelar utilizando Rails. Una de las tablas tiene una columna llamada attributes, que es un nombre reservado por Rails, creo.¿Cómo puedo ignorar permanentemente una columna de base de datos en mi clase ActiveRecord :: Base?

Aquí es el SQL para la tabla:

CREATE TABLE `album` (
    `id` int(11) NOT NULL, 
    `artist` int(11) NOT NULL, 
    `name` varchar(255) NOT NULL, 
    `gid` char(36) NOT NULL, 
    `modpending` int(11) DEFAULT '0', 
    `attributes` int(11) DEFAULT '0', 
    ... 
); 

Aquí es mi clase ActiveRecord:

class Album < ActiveRecord::Base 
    set_table_name "album" 
    belongs_to :artist 
    has_many :tracks, :through => :album_tracks 
end 

Esto es lo que sucede cuando trato de crear una instancia:

[email protected]:~/Sites/logdb (master *)$ rails c 
Loading development environment (Rails 3.0.3) 
no such file to load -- irbtools 
ruby-1.9.2-p0 > x = Album.find_by_name("Champ") 
=> #<Album id: 969139, artist: 354493, name: "Champ", gid: "15a9a4b8-9dd9-4f6f-b4e9-7c69948af88f", modpending: 0, attributes: 1100, page: 143735328, language: 120, script: 28, modpending_lang: nil, quality: -1, modpending_qual: 0> 
ruby-1.9.2-p0 > x.name 
ActiveRecord::DangerousAttributeError: attributes_before_type_cast is defined by ActiveRecord 
    from /Users/hornairs/.rvm/gems/[email protected]/gems/activerecord-3.0.3/lib/active_record/attribute_methods.rb:23:in `instance_method_already_implemented?' 
    from /Users/hornairs/.rvm/gems/[email protected]/gems/activemodel-3.0.3/lib/active_model/attribute_methods.rb:263:in `block (2 levels) in define_attribute_methods' 
    from /Users/hornairs/.rvm/gems/[email protected]/gems/activemodel-3.0.3/lib/active_model/attribute_methods.rb:262:in `each' 
    from /Users/hornairs/.rvm/gems/[email protected]/gems/activemodel-3.0.3/lib/active_model/attribute_methods.rb:262:in `block in define_attribute_methods' 
    from /Users/hornairs/.rvm/gems/[email protected]/gems/activemodel-3.0.3/lib/active_model/attribute_methods.rb:261:in `each' 
    from /Users/hornairs/.rvm/gems/[email protected]/gems/activemodel-3.0.3/lib/active_model/attribute_methods.rb:261:in `define_attribute_methods' 
    from /Users/hornairs/.rvm/gems/[email protected]/gems/activerecord-3.0.3/lib/active_record/attribute_methods.rb:13:in `define_attribute_methods' 
    from /Users/hornairs/.rvm/gems/[email protected]/gems/activerecord-3.0.3/lib/active_record/attribute_methods.rb:41:in `method_missing' 
    from /Users/hornairs/.rvm/gems/[email protected]/gems/thwart-0.0.4/lib/thwart/canable.rb:27:in `method_missing' 
    from (irb):2 
    from /Users/hornairs/.rvm/gems/[email protected]/gems/railties-3.0.3/lib/rails/commands/console.rb:44:in `start' 
    from /Users/hornairs/.rvm/gems/[email protected]/gems/railties-3.0.3/lib/rails/commands/console.rb:8:in `start' 
    from /Users/hornairs/.rvm/gems/[email protected]/gems/railties-3.0.3/lib/rails/commands.rb:23:in `<top (required)>' 
    from script/rails:6:in `require' 
    from script/rails:6:in `<main>' 
ruby-1.9.2-p0 > 

Se parece que el nombre attributes está reservado, por lo que me gustaría encontrar una forma de ignorarlo para todos consultas y tienen AR ignorarlo al reflexionar sobre el esquema para definir la clase de modelo. ¿Alguna sugerencia? ¡Gracias!

+0

No conozco la solución, pero encontré un hilo con alguien que tiene el mismo problema: . No estoy seguro de que sea de ayuda. – Robin

Respuesta

9

resuelto este usando una combinación de cosas de enlace de Robin y algunas otras respuestas para

class Album < ActiveRecord::Base 
    set_table_name "album" 

    class << self 
    def instance_method_already_implemented?(method_name) 
     return true if method_name =~ /^attributes/ 
     super 
    end 
    end 

    belongs_to :artist 
    has_many :tracks, :through => :album_tracks 
end 

hizo el truco. Utilicé un gran cambio de barrido para devolver verdadero sin arrojar un error para todos los métodos que comienzan con attributes, y no creo que haya causado ningún problema en otro lugar.

9
class << self 
    def instance_method_already_implemented?(method_name) 
     return true if method_name =~ /^attributes/ 
     super 
    end 
    end 

Este parche está muy bien y estaba trabajando para mí sobre todo, pero cuando se echa algo así como Album.column_names y Album.columns.collect (&: nombre) que sería aún así obtener todas las columnas. También esto fallaría.

a = Album.last 
a = Album.new(a.attributes) 

Para tener carriles totalmente ignorar una columna puede hacer esto.

class Album < ActiveRecord::Base 
    set_table_name "album" 
    ## --------------------- Ignore columns patch ------ 
    @@ignore_column_pattern = /^column_one|^column_two/ 

    class << self 
     alias :all_columns :columns 
     def columns 
     @columns_filt ||= all_columns.reject { |col| col.name =~ @@ignore_column_pattern } 
     end 
    end 

    alias :all_attribute_names :attribute_names 
    def attribute_names 
     @attr_names_filt ||= all_attribute_names.reject { |att| att =~ @@ignore_column_pattern } 
    end 
    ## -------------------/Ignore columns patch ------ 
    belongs_to :artist 
    has_many :tracks, :through => :album_tracks 
    end 

También utilicé una matriz para almacenar las columnas que no quería pero aún se podía utilizar la forma de expresiones regulares también! Ahora, la única manera en que puede averiguar sobre la columna es utilizando la conexión, es decir.

Album.connection.columns("albums").collect(&:name) 
3

(Esta es una vieja pregunta, pero aún figura en Google así que voy a añadir una respuesta tardía)

que he encontrado la mejor manera de restringir los datos cargados por un modelo ActiveRecord es crear una vista de base de datos que solo contiene las columnas que desea cargar. Puede apuntar su modelo ActiveRecord a la vista restringida utilizando el método table_name de ActiveRecord. Las herramientas SQL nativas aún pueden manipular la tabla subyacente, pero ActiveRecord solo verá (y en consecuencia cargará) las columnas explícitamente incluidas en la vista.

Cuestiones relacionadas