Jump to content

The ultimate community for Ruby on Rails developers.


Photo

How to check if a Rails model exists ('defined?' not working)


  • Please log in to reply
3 replies to this topic

#1 Senktec

Senktec

    Passenger

  • Members
  • 6 posts
  • LocationUK

Posted 09 October 2013 - 08:20 AM

I have some code that performs some additional functionality when a specific model has been provided by another gem, or by the app. My code is checking that the model exists along the lines:
if defined? MyModel
  # do stuff with MyModel
end

It appears that this does not always work as I had intend. I am seeing "defined? MyModel" returning nil when the check is performed in development and test modes if it runs before the model has been used. I think the code below is a minimal example to show what I'm getting. I have not seen this problem when running the app in production, so perhaps there is some lazy loading going on?

 
My questions are:
  • What is the best way to check a model exists?
  • If using defined? is correct and works in production, how should I test the code? At the moment within my rspec feature tests, the call to "defined? MyModel" in the templates returns nil, so additional functionality is not included in the page.
In this example, first time "defined? MyModel" is called it returns nil, however, after the model has been used, it correctly returns "constant".
$ rails new test_model_exists
$ cd test_model_exists
$ rails generate model MyModel
$ bundle exec rake db:migrate
$ bundle exec rails console
Loading development environment (Rails 4.0.0)
2.0.0-p247 :001 > defined? MyModel
  => nil 
2.0.0-p247 :002 > MyModel
  => MyModel(id: integer, created_at: datetime, updated_at: datetime) 
2.0.0-p247 :004 > defined? MyModel
  => "constant" 
I am using: rails 4.0.0, ruby 2.0.0, rspec-rails 2.14.0.


#2 james

james

    Guard

  • Moderators
  • 221 posts
  • LocationLeeds, U.K.

Posted 09 October 2013 - 09:05 AM   Best Answer

The problem as far as I can tell is exactly what you expect. In Development mode everything is loaded and reloaded on demand, this is to allow changes to be made and reviewed in the browser without the need to restart the server for every change.

 

The offending line i believe is the eager load option.

 

From the production.rb environment file

  # Eager load code on boot. This eager loads most of Rails and
  # your application in memory, allowing both thread web servers
  # and those relying on copy on write to perform better.
  # Rake tasks automatically ignore this option for performance.
  config.eager_load = true

You will see that in development and test rb files this value is set to false. Try changing it to true and see if that helps


Programming is just about problem solving!


#3 Senktec

Senktec

    Passenger

  • Members
  • 6 posts
  • LocationUK

Posted 09 October 2013 - 12:23 PM

Yes, setting eager_load = true in development.rb and test.rb fixes this for me. Thanks for the quick reply james.

 

Alternatively, if the models are defined within a Rails::Engine, it appears it's possible to call eager_load! from within spec_helper.rb to load those models:

MyRailsEngine::Engine.eager_load!


#4 james

james

    Guard

  • Moderators
  • 221 posts
  • LocationLeeds, U.K.

Posted 09 October 2013 - 12:46 PM

 

Yes, setting eager_load = true in development.rb and test.rb fixes this for me. Thanks for the quick reply james.

 

Alternatively, if the models are defined within a Rails::Engine, it appears it's possible to call eager_load! from within spec_helper.rb to load those models:

MyRailsEngine::Engine.eager_load!

 

If that works for you then it would be a better option as it will enable the development environment to behave as normal which is important for apps that use the engine


Programming is just about problem solving!





0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users