如何永久忽略ActiveRecord :: Base类中的数据库列?

我有一个遗留数据库,我正在尝试使用Rails进行建模。 其中一个表有一个名为attributes的列,我认为这是Rails保留的名称。

这是表的SQL:

 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', ... ); 

这是我的ActiveRecord类:

 class Album  :album_tracks end 

以下是我尝试实例化实例时发生的情况:

 hornairs@bishop:~/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") => # ruby-1.9.2-p0 > x.name ActiveRecord::DangerousAttributeError: attributes_before_type_cast is defined by ActiveRecord from /Users/hornairs/.rvm/gems/ruby-1.9.2-p0@logdb/gems/activerecord-3.0.3/lib/active_record/attribute_methods.rb:23:in `instance_method_already_implemented?' from /Users/hornairs/.rvm/gems/ruby-1.9.2-p0@logdb/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/ruby-1.9.2-p0@logdb/gems/activemodel-3.0.3/lib/active_model/attribute_methods.rb:262:in `each' from /Users/hornairs/.rvm/gems/ruby-1.9.2-p0@logdb/gems/activemodel-3.0.3/lib/active_model/attribute_methods.rb:262:in `block in define_attribute_methods' from /Users/hornairs/.rvm/gems/ruby-1.9.2-p0@logdb/gems/activemodel-3.0.3/lib/active_model/attribute_methods.rb:261:in `each' from /Users/hornairs/.rvm/gems/ruby-1.9.2-p0@logdb/gems/activemodel-3.0.3/lib/active_model/attribute_methods.rb:261:in `define_attribute_methods' from /Users/hornairs/.rvm/gems/ruby-1.9.2-p0@logdb/gems/activerecord-3.0.3/lib/active_record/attribute_methods.rb:13:in `define_attribute_methods' from /Users/hornairs/.rvm/gems/ruby-1.9.2-p0@logdb/gems/activerecord-3.0.3/lib/active_record/attribute_methods.rb:41:in `method_missing' from /Users/hornairs/.rvm/gems/ruby-1.9.2-p0@logdb/gems/thwart-0.0.4/lib/thwart/canable.rb:27:in `method_missing' from (irb):2 from /Users/hornairs/.rvm/gems/ruby-1.9.2-p0@logdb/gems/railties-3.0.3/lib/rails/commands/console.rb:44:in `start' from /Users/hornairs/.rvm/gems/ruby-1.9.2-p0@logdb/gems/railties-3.0.3/lib/rails/commands/console.rb:8:in `start' from /Users/hornairs/.rvm/gems/ruby-1.9.2-p0@logdb/gems/railties-3.0.3/lib/rails/commands.rb:23:in `' from script/rails:6:in `require' from script/rails:6:in `' ruby-1.9.2-p0 > 

看起来好像attributes名称是保留的,所以我想找到一些方法来忽略所有查询,并在反映模式来定义模型类时让AR忽略它。 有什么建议? 谢谢!

使用罗宾链接和其他一些SO答案的组合解决了这个问题

 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 

诀窍。 我使用了一个大的彻底更改来返回true而不会为所有以attributes开头的方法抛出错误,我不认为它在其他地方引起任何问题。

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

这个补丁很好,主要是为我工作,但当你检查像Album.column_names和Album.columns.collect(&:name)之类的东西时,你仍然可以获得所有列。 这也会失败。

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

要让rails完全忽略列,您可以执行此操作。

  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 

我还使用一个数组来存储我不想要的列,但你仍然可以使用正则表达式方式! 现在,您可以找到有关该列的唯一方法是使用连接即。

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

(这是一个古老的问题,但仍然在谷歌的数字,所以我会添加一个迟来的答案)

我发现限制ActiveRecord模型加载的数据的最佳方法是创建一个仅包含要加载的列的数据库视图。 您可以使用ActiveRecord的table_name方法将ActiveRecord模型指向约束视图。 本机SQL工具仍然可以操作基础表,但ActiveRecord只会查看(并因此加载)视图中明确包含的列。