I've just had the irritating experience of:
$rake db:create
rake aborted!
Unknown database 'foo'
... which resulted from a plugin's ActiveRecord model referencing an unknown constant like so:
class Tag < ActiveRecord::Base
class Jail < Safemode::Jail
allow :id, :name
end
end
At this point the class Safemode::Jail was not defined yet, so Dependencies#load_missing_constant kicked in.
Dependencies#load_missing_constant first calls #log_call which builds a log message and sends it to #log. While building the log message it calls #inspect on the ActiveRecord model which tries to look up the table and then fails with the message "Unknown database 'foo'".
The error message above was obviously a little confusing :)
But I also wondered why that whole log message is composed for every call to several Dependencies methods even though #log would only use it (and actually log something) if RAILS_DEFAULT_LOGGER is defined and the log_activity flag is set to true (defaults to false).
def log_call(*args)
arg_str = args.collect(&:inspect) * ', '
/in `([a-z_\?\!]+)'/ =~ caller(1).first
selector = $1 || '<unknown>'
log "called #{selector}(#{arg_str})"
end
def log(msg)
if defined?(RAILS_DEFAULT_LOGGER) && RAILS_DEFAULT_LOGGER && log_activity
RAILS_DEFAULT_LOGGER.debug "Dependencies: #{msg}"
end
end
I suggest to skip the log message building part in #log_call for those cases when #log wouldn't do anything anyways:
def log_call(*args)
return unless defined?(RAILS_DEFAULT_LOGGER) && RAILS_DEFAULT_LOGGER && log_activity
...
This would also allow Dependencies to actually load the missing constant in that scenario mentioned above.
Additionally I wonder if it's a good idea to change ActiveRecord::Base#inspect so that it doesn't bomb when the database does not exist?