0

Rails: 3.2.11

I have this module in lib and required in application.rb. I'd like to make the constant FORBIDDEN_USERNAMES available throughout the app. The constant is an array of values generated from the routes. I can't make this an initializer because the routes haven't been loaded yet.

What I have below doesn't work as FORBIDDEN_USERNAMES returns an empty array.

# in lib
module ForbiddenUsernames    
  def self.names
    Rails.application.reload_routes!
    all_routes = Rails.application.routes.routes

    all_names = Array.new
    all_routes.each do |route|
      # populate all_names array
    end
    all_names.uniq
  end
end

FORBIDDEN_USERNAMES = ForbiddenUsernames.names
# when ForbiddenUsernames.names is called by itself, it does not return [] or nil

Throughout the app, how do I make it so that I can just use FORBIDDEN_USERNAMES? Thank you!

David Nix
  • 3,324
  • 3
  • 32
  • 51
  • Perhaps this would be some help. I.e. put the code in an `after_initialize` block: http://stackoverflow.com/questions/8707495/rails-initializer-that-runs-after-routes-are-loaded – Casper Feb 02 '13 at 06:38
  • you can just write `[]` instead of `Array.new` – AJcodez Feb 02 '13 at 08:57

1 Answers1

1

I don't understand why you want this to be a constant. It seems to me you could use memoizable behavior.

# Wherever in your controller. Add helper_method if you need in the view (but would seem wrong)
def forbidden_usernames
  @forbidden_usernames ||= ForbiddenUsernames.names
end
helper_method :forbidden_usernames

ForbiddenUsernames.names will be called if @forbidden_usernames is nil, so it only happen once.

Update

# app/models/user.rb
def forbidden_usernames
  @forbidden_usernames ||= ForbiddenUsernames.names
end

def validate_not_forbidden
  !forbidden_usernames.include?(self.name)
end

If ever you need this functionality in more than one model, use modules. You can also have the forbidden_usernames memoized method in the module itself.

module ForbiddenUsernames    
  def self.names
    @forbidden_names ||= self.populates_all_names
  end

  protected

  def populate_all_names
    Rails.application.reload_routes!
    all_routes = Rails.application.routes.routes

    all_names = Array.new
    all_routes.each do |route|
      # populate all_names array
    end
    all_names.uniq
  end
end
mathieugagne
  • 2,465
  • 1
  • 17
  • 18