Module: Routable

Extended by:
ActiveSupport::Concern
Includes:
CaseSensitivity
Included in:
Namespace, Project
Defined in:
app/models/concerns/routable.rb

Overview

Store object full path in separate table for easy lookup and uniq validation Object must have name and path db fields and respond to parent and parent_changed? methods.

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.find_by_full_path(path, follow_redirects: false, route_scope: Route, redirect_route_scope: RedirectRoute) ⇒ Object

Finds a Routable object by its full path, without knowing the class.

Usage:

Routable.find_by_full_path('groupname')             # -> Group
Routable.find_by_full_path('groupname/projectname') # -> Project

Returns a single object, or nil.


17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'app/models/concerns/routable.rb', line 17

def self.find_by_full_path(path, follow_redirects: false, route_scope: Route, redirect_route_scope: RedirectRoute)
  return unless path.present?

  # Case sensitive match first (it's cheaper and the usual case)
  # If we didn't have an exact match, we perform a case insensitive search
  #
  # We need to qualify the columns with the table name, to support both direct lookups on
  # Route/RedirectRoute, and scoped lookups through the Routable classes.
  route =
    route_scope.find_by(routes: { path: path }) ||
    route_scope.iwhere(Route.arel_table[:path] => path).take

  if follow_redirects
    route ||= redirect_route_scope.iwhere(RedirectRoute.arel_table[:path] => path).take
  end

  return unless route

  route.is_a?(Routable) ? route : route.source
end

Instance Method Details

#build_full_pathObject


148
149
150
151
152
153
154
# File 'app/models/concerns/routable.rb', line 148

def build_full_path
  if parent && path
    parent.full_path + '/' + path
  else
    path
  end
end

#full_nameObject


98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'app/models/concerns/routable.rb', line 98

def full_name
  # We have to test for persistence as the cache key uses #updated_at
  return (route&.name || build_full_name) unless persisted? && Feature.enabled?(:cached_route_lookups, self, type: :ops)

  # Return the name as-is if the parent is missing
  return name if route.nil? && parent.nil? && name.present?

  # If the route is already preloaded, return directly, preventing an extra load
  return route.name if route_loaded? && route.present?

  # Similarly, we can allow the build if the parent is loaded
  return build_full_name if parent_loaded?

  Gitlab::Cache.fetch_once([cache_key, :full_name]) do
    route&.name || build_full_name
  end
end

#full_pathObject


116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'app/models/concerns/routable.rb', line 116

def full_path
  # We have to test for persistence as the cache key uses #updated_at
  return (route&.path || build_full_path) unless persisted? && Feature.enabled?(:cached_route_lookups, self, type: :ops)

  # Return the path as-is if the parent is missing
  return path if route.nil? && parent.nil? && path.present?

  # If the route is already preloaded, return directly, preventing an extra load
  return route.path if route_loaded? && route.present?

  # Similarly, we can allow the build if the parent is loaded
  return build_full_path if parent_loaded?

  Gitlab::Cache.fetch_once([cache_key, :full_path]) do
    route&.path || build_full_path
  end
end

#full_path_componentsObject


144
145
146
# File 'app/models/concerns/routable.rb', line 144

def full_path_components
  full_path.split('/')
end

#owned_by?(user) ⇒ Boolean

Group would override this to check from association

Returns:

  • (Boolean)

157
158
159
# File 'app/models/concerns/routable.rb', line 157

def owned_by?(user)
  owner == user
end

#parent_loaded?Boolean

Overriden in the Project model parent_id condition prevents issues with parent reassignment

Returns:

  • (Boolean)

136
137
138
# File 'app/models/concerns/routable.rb', line 136

def parent_loaded?
  association(:parent).loaded?
end

#route_loaded?Boolean

Returns:

  • (Boolean)

140
141
142
# File 'app/models/concerns/routable.rb', line 140

def route_loaded?
  association(:route).loaded?
end