Как я могу навсегда игнорировать столбец базы данных в моем классе ActiveRecord :: Base? - PullRequest
7 голосов
/ 06 февраля 2011

У меня есть устаревшая база данных, которую я пытаюсь смоделировать с помощью 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 < ActiveRecord::Base
  set_table_name "album"
  belongs_to :artist
  has_many :tracks, :through => :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")
 => #<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/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 `<top (required)>'
  from script/rails:6:in `require'
  from script/rails:6:in `<main>'
ruby-1.9.2-p0 > 

Выглядит так, как будто имя attributes зарезервировано, поэтому я хотел бы найти какой-нибудь способигнорировать его для всех запросов и заставить AR игнорировать его при отражении в схеме для определения класса модели.Какие-либо предложения?Спасибо!

Ответы [ 3 ]

9 голосов
/ 25 апреля 2012
  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) 

Чтобы рельсы полностью игнорировали столбец, вы можете сделать это.

 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)
9 голосов
/ 06 февраля 2011

Решил это, используя комбинацию из ссылки Робина и некоторых других 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, и я не думаю, что это вызвало какие-либо проблемы в других местах.

3 голосов
/ 16 мая 2015

(Это старый вопрос, но он все еще фигурирует в Google, поэтому я добавлю запоздалый ответ)

Я нашел, что лучший способ ограничить данные, загружаемые моделью ActiveRecord, - это создать представление базы данных, содержащее только те столбцы, которые вы хотите загрузить. Вы можете указать свою модель ActiveRecord на ограниченное представление, используя метод ActiveRecord table_name . Инструменты собственного SQL все еще могут манипулировать базовой таблицей, но ActiveRecord будет видеть (и, следовательно, загружать) только столбцы, явно включенные в представление.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...