Undefined class method in Rails model using ActiveModel

830 views Asked by At

I have a database-less (no active_record) Rails 4.2 application with two tableless models that use the ActiveModel::Model module.

(The posted code is simplified but results are real and same regardless.)


First model: Group, defined in app/models/group.rb:

class Group
    include ActiveModel::Model

    def self.works?
        true
    end
end

Everything works, both in app and in console:

irb(main):001:0> Group.works?
=> true
irb(main):002:0> Group.instance_methods
=> [:model_name, :validation_context, :validation_context=, :_validate_callbacks, :_validate_callbacks?, :_validate_callbacks=, :_run_validate_callbacks, :_validators, :_validators?, :_validators=, :persisted?, :to_model, :to_key, :to_param, :to_partial_path, :validates_absence_of, :validates_acceptance_of, :validates_confirmation_of, :validates_exclusion_of, :validates_format_of, :validates_inclusion_of, :validates_length_of, :validates_size_of, :validates_numericality_of, :validates_presence_of, :run_callbacks, :errors, :valid?, :validate, :invalid?, :read_attribute_for_validation, :run_validations!, :validates_with, :blank?, :present?, :presence, :acts_like?, :duplicable?, :deep_dup, :try, :try!, :in?, :presence_in, :to_query, :instance_values, :instance_variable_names, :to_json_with_active_support_encoder, :to_json_without_active_support_encoder, :to_json, :as_json, :with_options, :html_safe?, :is_haml?, :psych_to_yaml, :to_yaml, :to_yaml_properties, :`, :require_or_load, :require_dependency, :load_dependency, :unloadable, :pretty_print, :pretty_print_cycle, :pretty_print_instance_variables, :pretty_print_inspect, :nil?, :===, :=~, :!~, :eql?, :hash, :<=>, :class, :singleton_class, :clone, :dup, :itself, :taint, :tainted?, :untaint, :untrust, :untrusted?, :trust, :freeze, :frozen?, :to_s, :inspect, :methods, :singleton_methods, :protected_methods, :private_methods, :public_methods, :instance_variables, :instance_variable_get, :instance_variable_set, :instance_variable_defined?, :remove_instance_variable, :instance_of?, :kind_of?, :is_a?, :tap, :send, :public_send, :respond_to?, :extend, :display, :method, :public_method, :singleton_method, :define_singleton_method, :object_id, :to_enum, :enum_for, :gem, :silence_warnings, :enable_warnings, :with_warnings, :silence_stderr, :silence_stream, :suppress, :capture, :silence, :quietly, :class_eval, :pretty_inspect, :byebug, :debugger, :concern, :suppress_warnings, :==, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__, :__id__]

Second model: Banner, defined in app/models/banner.rb with exact same code as in Group:

class Banner
    include ActiveModel::Model

    def self.works?
        true
    end
end

This one, however, doesn't work:

irb(main):001:0> Banner.works?
NoMethodError: undefined method `works?' for Banner:Module (trace omitted)
irb(main):002:0* Banner.instance_methods
=> []

I've tried doing nasty things to the model, redundantly adding require "active_model" (some posts indicated that such an issue might arise due to lazy-loading of classes or something and this could fix it), and straight copy-pasting code from one model to the other, changing only the class name (like in the samples) but no luck.

1

There are 1 answers

1
Sergio Tulentsev On BEST ANSWER

Read the error closely

NoMethodError: undefined method `works?' for Banner:Module

See Banner:Module? You have some other Banner, which is a module, and it's loaded in place of your model (thus, shadowing it).

Most often, this is caused by rails' lazy-loading. As to what is the remedy here, it depends on your concrete situation. Common options are:

  • not doing lazy-loading (loading classes eagerly instead)
  • specifying FQN (fully qualified name), in case this is a local name vs global name conflict.
  • requiring model file explicitly (something like `require 'app/models/banner.rb')