How can I permanently ignore a database column in my ActiveRecord::Base class?

后端 未结 3 2024
小蘑菇
小蘑菇 2021-01-18 04:25

I have a legacy database which I\'m trying to model using Rails. One of the tables has a column named attributes, which is a name reserved by Rails I think.

相关标签:
3条回答
  • 2021-01-18 04:47
      class << self
         def instance_method_already_implemented?(method_name)
          return true if method_name =~ /^attributes/
          super
        end
      end
    

    This patch is fine and was working for me mostly, but when you check something like Album.column_names and Album.columns.collect(&:name) you would still get all columns. Also this would fail.

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

    To have rails fully ignore a column you could do this.

     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
    

    Also I used an array to store the columns I didn't want but you could still use the regex way too! Now the only way that you can find out about the column is using connection ie.

    Album.connection.columns("albums").collect(&:name)
    
    0 讨论(0)
  • 2021-01-18 04:59

    (This is an old question but still figures in Google so I'll add a belated answer)

    I've found the best way to restrict data loaded by an ActiveRecord model is to create a database view that only contains the columns you wish to load. You can point your ActiveRecord model at the constrained view using ActiveRecord's table_name method. Native SQL tools can still manipulate the underlying table, but ActiveRecord will only see (and consequently load) the columns explicitly included in the view.

    0 讨论(0)
  • 2021-01-18 05:01

    Solved this using a combination of stuff from Robin's link and some other SO answers

    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
    

    Did the trick. I used a big sweeping change to return true without throwing an error for all methods starting with attributes, and I don't think its caused any problems elsewhere.

    0 讨论(0)
提交回复
热议问题