class JsRoutes

Constants

DEFAULTS
DEFAULT_PATH

OPTIONS

FILTERED_DEFAULT_PARTS
LAST_OPTIONS_KEY
NODE_TYPES
URL_OPTIONS
VERSION

Public Class Methods

assert_usable_configuration!() click to toggle source

Under rails 3.1.1 and higher, perform a check to ensure that the full environment will be available during asset compilation. This is required to ensure routes are loaded.

# File lib/js_routes.rb, line 104
def assert_usable_configuration!
  if 3 == Rails::VERSION::MAJOR && !Rails.application.config.assets.initialize_on_precompile
    raise("Cannot precompile js-routes unless environment is initialized. Please set config.assets.initialize_on_precompile to true.")
  end
  true
end
configuration() click to toggle source
# File lib/js_routes.rb, line 85
def configuration
  @configuration ||= Configuration.new
end
generate(opts = {}) click to toggle source
# File lib/js_routes.rb, line 89
def generate(opts = {})
  new(opts).generate
end
generate!(file_name=nil, opts = {}) click to toggle source
# File lib/js_routes.rb, line 93
def generate!(file_name=nil, opts = {})
  if file_name.is_a?(Hash)
    opts = file_name
    file_name = opts[:file]
  end
  new(opts).generate!(file_name)
end
json(string) click to toggle source
# File lib/js_routes.rb, line 111
def json(string)
  ActiveSupport::JSON.encode(string)
end
new(options = {}) click to toggle source

Implementation

# File lib/js_routes.rb, line 120
def initialize(options = {})
  @configuration = self.class.configuration.merge(options)
end
options() click to toggle source
# File lib/js_routes.rb, line 80
def options
  ActiveSupport::Deprecation.warn('JsRoutes.options method is deprecated use JsRoutes.configuration instead')
  configuration
end
setup(&block) click to toggle source
# File lib/js_routes.rb, line 76
def setup(&block)
  configuration.tap(&block) if block
end

Public Instance Methods

generate() click to toggle source
# File lib/js_routes.rb, line 124
def generate
  # Ensure routes are loaded. If they're not, load them.
  if named_routes.to_a.empty? && application.respond_to?(:reload_routes!)
    application.reload_routes!
  end

  {
    "GEM_VERSION"         => JsRoutes::VERSION,
    "ROUTES"              => js_routes,
    "DEPRECATED_BEHAVIOR" => Rails.version < "4",
    "NODE_TYPES"          => json(NODE_TYPES),

    "APP_CLASS"           => application.class.to_s,
    "NAMESPACE"           => json(@configuration.namespace),
    "DEFAULT_URL_OPTIONS" => json(@configuration.default_url_options),
    "PREFIX"              => json(@configuration.prefix),
    "SPECIAL_OPTIONS_KEY" => json(@configuration.special_options_key),
    "SERIALIZER"          => @configuration.serializer || json(nil),
  }.inject(File.read(File.dirname(__FILE__) + "/routes.js")) do |js, (key, value)|
    js.gsub!(key, value.to_s)
  end
end
generate!(file_name = nil) click to toggle source
# File lib/js_routes.rb, line 147
def generate!(file_name = nil)
  # Some libraries like Devise do not yet loaded their routes so we will wait
  # until initialization process finish
  # https://github.com/railsware/js-routes/issues/7
  Rails.configuration.after_initialize do
    file_name ||= self.class.configuration['file']
    File.open(Rails.root.join(file_name), 'w') do |f|
      f.write generate
    end
  end
end

Protected Instance Methods

any_match?(route, parent_route, matchers) click to toggle source
# File lib/js_routes.rb, line 204
def any_match?(route, parent_route, matchers)
  full_route = [parent_route.try(:name), route.name].compact.join('_')

  matchers = Array(matchers)
  matchers.any? {|regex| full_route =~ regex}
end
application() click to toggle source
# File lib/js_routes.rb, line 161
def application
  @configuration.application
end
build_js(route, parent_route) click to toggle source
# File lib/js_routes.rb, line 211
  def build_js(route, parent_route)
    name = [parent_route.try(:name), route.name].compact
    route_name = generate_route_name(name, (:path unless @configuration[:compact]))
    parent_spec = parent_route.try(:path).try(:spec)
    route_arguments = route_js_arguments(route, parent_spec)
    url_link = generate_url_link(name, route_name, route_arguments, route)
    _ = <<-JS.strip!
  // #{name.join('.')} => #{parent_spec}#{route.path.spec}
  // function(#{build_params(route.required_parts)})
  #{route_name}: Utils.route(#{route_arguments})#{",\n" + url_link if url_link.length > 0}
  JS
  end
build_params(required_parts) click to toggle source
# File lib/js_routes.rb, line 260
def build_params(required_parts)
  params = required_parts + [LAST_OPTIONS_KEY]
  params.join(", ")
end
build_route_if_match(route, parent_route=nil) click to toggle source
# File lib/js_routes.rb, line 196
def build_route_if_match(route, parent_route=nil)
  if any_match?(route, parent_route, @configuration[:exclude]) || !any_match?(route, parent_route, @configuration[:include])
    nil
  else
    build_js(route, parent_route)
  end
end
generate_route_name(name, suffix) click to toggle source
# File lib/js_routes.rb, line 250
def generate_route_name(name, suffix)
  route_name = name.join('_')
  route_name << "_#{ suffix }" if suffix
  @configuration[:camel_case] ? route_name.camelize(:lower) : route_name
end
get_app_from_route(route) click to toggle source
# File lib/js_routes.rb, line 187
def get_app_from_route(route)
  # rails engine in Rails 4.2 use additional ActionDispatch::Routing::Mapper::Constraints, which contain app
  if route.app.respond_to?(:app) && route.app.respond_to?(:constraints)
    route.app.app
  else
    route.app
  end
end
js_routes() click to toggle source
# File lib/js_routes.rb, line 169
def js_routes
  js_routes = named_routes.sort_by(&:first).flat_map do |_, route|
    [build_route_if_match(route)] + mounted_app_routes(route)
  end.compact
  "{\n" + js_routes.join(",\n") + "}\n"
end
json(string) click to toggle source
# File lib/js_routes.rb, line 256
def json(string)
  self.class.json(string)
end
mounted_app_routes(route) click to toggle source
# File lib/js_routes.rb, line 176
def mounted_app_routes(route)
  rails_engine_app = get_app_from_route(route)
  if rails_engine_app.respond_to?(:superclass) && rails_engine_app.superclass == Rails::Engine && !route.path.anchored
    rails_engine_app.routes.named_routes.map do |_, engine_route|
      build_route_if_match(engine_route, route)
    end
  else
    []
  end
end
named_routes() click to toggle source
# File lib/js_routes.rb, line 165
def named_routes
  application.routes.named_routes.to_a
end
route_js_arguments(route, parent_spec) click to toggle source
# File lib/js_routes.rb, line 224
def route_js_arguments(route, parent_spec)
  required_parts = route.required_parts
  parts_table = route.parts.each_with_object({}) do |part, hash|
    hash[part] = required_parts.include?(part)
  end
  default_options = route.defaults.select do |part, _|
    FILTERED_DEFAULT_PARTS.exclude?(part) && URL_OPTIONS.include?(part) || parts_table[part]
  end
  [
    # JS objects don't preserve the order of properties which is crucial,
    # so array is a better choice.
    parts_table.to_a,
    default_options,
    serialize(route.path.spec, parent_spec)
  ].map do |argument|
    json(argument)
  end.join(", ")
end
serialize(spec, parent_spec=nil) click to toggle source

This function serializes Journey route into JSON structure We do not use Hash for human readable serialization And preffer Array serialization because it is shorter. Routes.js file will be smaller.

# File lib/js_routes.rb, line 269
def serialize(spec, parent_spec=nil)
  return nil unless spec
  return spec.tr(':', '') if spec.is_a?(String)
  result = serialize_spec(spec, parent_spec)
  if parent_spec && result[1].is_a?(String)
    result = [
      # We encode node symbols as integer
      # to reduce the routes.js file size
      NODE_TYPES[:CAT],
      serialize_spec(parent_spec),
      result
    ]
  end
  result
end
serialize_spec(spec, parent_spec=nil) click to toggle source
# File lib/js_routes.rb, line 285
def serialize_spec(spec, parent_spec=nil)
  [
    NODE_TYPES[spec.type],
    serialize(spec.left, parent_spec),
    spec.respond_to?(:right) && serialize(spec.right)
  ]
end