简体   繁体   中英

Rails: how to extend a gem's ActiveRecord child class?

Im having problems extending a class which is defined in a gem and is a child of ActiveRecord::Base.

The only thing i'd like to extend this class with is: has_many :promos

The extending however tends to rule out the original class. The errors i'm getting:

PGError: ERROR:  relation "sites" does not exist
LINE 4:              WHERE a.attrelid = '"sites"'::regclass
                                        ^
:             SELECT a.attname, format_type(a.atttypid, a.atttypmod), d.adsrc, a.attnotnull
              FROM pg_attribute a LEFT JOIN pg_attrdef d
                ON a.attrelid = d.adrelid AND a.attnum = d.adnum
             WHERE a.attrelid = '"sites"'::regclass
               AND a.attnum > 0 AND NOT a.attisdropped
             ORDER BY a.attnum

Checking the class in the console gives:

Cms::Site(Table doesn't exist)

The original class has this method which probably isn't invoked anymore:

set_table_name :cms_sites

Btw. i'm trying to extend the Site class from the comfortable_mexican_sofa plugin.

This is the file which should extend the class:

# lib/comfortable_media_sofa/comfortable_media_sofa.rb
require 'comfortable_mexican_sofa'

module Cms
  class Site < ActiveRecord::Base
    has_many :promos
  end
end

Which gets loaded here:

require File.expand_path('../boot', __FILE__)

require 'rails/all'

Bundler.require(:default, Rails.env) if defined?(Bundler)

module Mkturbo
  class Application < Rails::Application
    config.autoload_paths += %W(#{config.root}/vendor/gems/comfortable_mexican_sofa-0.0.18)
    config.autoload_paths += %W(#{config.root}/lib/comfortable_media_sofa)
    config.plugins = [ :comfortable_mexican_sofa, :comfortable_media_sofa, :all ]

    # ....
  end
end

And is required in the top of the comfortable_mexican_sofa initializer:

# config/initializers/comfortable_mexican_sofa.rb
require 'comfortable_media_sofa'

How can i do this? Is a requirement order issue or am i extending it the wrong way? Many thanks in advance!

In your example you're completely overwriting that class. You just need to inject things into it... something like this:

module MyModule
  def self.included(base)
    base.has_many :things
  end
end
Cms::Site.send(:include, MyModule)

Then just to see if the association kicks in:

ruby-1.9.2-p180 :005 > s = Cms::Site.new
=> #<Cms::Site id: nil, label: nil, hostname: nil> 
ruby-1.9.2-p180 :006 > s.things
NameError: uninitialized constant Cms::Site::Thing

I actually put that module directly into sofa's initializer. Hope this helps.

The most obvious thing that jumps out at me is that you say you're "trying to extend the Site class from the comfortable-mexican-sofa plugin"

...but the class in your module is extending ActiveRecord::Base.

module Cms    
  class Site < ActiveRecord::Base
  ...

Maybe I'm reading it wrong, but it sounds like your class should be something like:

module Cms      
  class Site < CmsSite  // i.e. extending the class from comfortable-mexican-sofa
  ...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM