Class: Avo::Resources::ResourceManager

Inherits:
Object
  • Object
show all
Defined in:
lib/avo/resources/resource_manager.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeResourceManager

Returns a new instance of ResourceManager.



59
60
61
# File 'lib/avo/resources/resource_manager.rb', line 59

def initialize
  @resources = self.class.fetch_resources
end

Instance Attribute Details

#resourcesObject Also known as: all

Returns the value of attribute resources.



4
5
6
# File 'lib/avo/resources/resource_manager.rb', line 4

def resources
  @resources
end

Class Method Details

.buildObject



9
10
11
12
13
# File 'lib/avo/resources/resource_manager.rb', line 9

def build
  instance = new
  instance.check_bad_resources
  instance
end

.fetch_resourcesObject

Fetches the resources available to the application. We have two ways of doing that.

  1. Through eager loading.

We automatically eager load the resources directory and fetch the descendants from the scanned files. This is the simple way to get started.

  1. Manually, declared by the user.

We have this option to load the resources because when they are loaded automatically through eager loading, those Resource classes and their methods may trigger loading other classes. And that may disrupt Rails booting process. Ex: AdminResource may use self.model_class = User. That will trigger Ruby to load the User class and itself load other classes in a chain reaction. The scenario that comes up most often is when Rails boots, the routes are being computed which eager loads the resource files. At that boot time some migration might have not been run yet, but Rails tries to access them through model associations, and they are not available.

To enable this feature add a ‘resources` array config in your Avo initializer. config.resources = [

"UserResource",
"FishResource",

]



36
37
38
39
40
41
42
43
44
# File 'lib/avo/resources/resource_manager.rb', line 36

def fetch_resources
  if Avo.configuration.resources.present?
    load_configured_resources
  else
    load_resources_namespace
  end

  BaseResource.descendants
end

.load_configured_resourcesObject



50
51
52
53
54
55
56
# File 'lib/avo/resources/resource_manager.rb', line 50

def load_configured_resources
  raise "Resources configuration must be an array" unless Avo.configuration.resources.is_a? Array

  Avo.configuration.resources.each do |resource|
    resource.to_s.safe_constantize
  end
end

.load_resources_namespaceObject



46
47
48
# File 'lib/avo/resources/resource_manager.rb', line 46

def load_resources_namespace
  Rails.autoloaders.main.eager_load_namespace(Avo::Resources)
end

Instance Method Details

#check_bad_resourcesObject



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/avo/resources/resource_manager.rb', line 63

def check_bad_resources
  resources.each do |resource|
    has_model = resource.model_class.present?

    unless has_model
      possible_model = resource.to_s.gsub "Avo::Resources::", ""
      possible_model = possible_model.gsub "Resource", ""

      Avo.error_manager.add({
        url: "https://docs.avohq.io/3.0/resources.html#self_model_class",
        target: "_blank",
        message: "#{resource} does not have a valid model assigned. It failed to find the #{possible_model} model. \n\r Please create that model or assign one using self.model_class = YOUR_MODEL"
      })
    end
  end
end

#get_available_resources(user = nil) ⇒ Object



153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/avo/resources/resource_manager.rb', line 153

def get_available_resources(user = nil)
  valid_resources
    .select do |resource|
      resource.authorization.class.authorize(
        user,
        resource.model_class,
        Avo.configuration.authorization_methods.stringify_keys["index"],
        policy_class: resource.authorization_policy,
        raise_exception: false
      )
    end
    .sort_by { |r| r.name }
end

#get_model_class_by_name(name) ⇒ Object

Returns the Rails model class by singular snake_cased name

get_model_class_by_name(‘user’) => User



149
150
151
# File 'lib/avo/resources/resource_manager.rb', line 149

def get_model_class_by_name(name)
  name.to_s.camelize.singularize
end

#get_resource(resource) ⇒ Object

Returns the Avo resource by camelized name

get_resource_by_name(‘User’) => instance of Avo::Resources::User



88
89
90
91
92
93
94
# File 'lib/avo/resources/resource_manager.rb', line 88

def get_resource(resource)
  resource = "Avo::Resources::#{resource}" unless resource.to_s.starts_with?("Avo::Resources::")

  resources.find do |available_resource|
    resource.to_s == available_resource.to_s
  end
end

#get_resource_by_controller_name(name) ⇒ Object

Returns the Avo resource by singular snake_cased name

get_resource_by_controller_name(‘delayed_backend_active_record_jobs’) => instance of Avo::Resources::DelayedJob get_resource_by_controller_name(‘users’) => instance of Avo::Resources::User



134
135
136
137
138
139
# File 'lib/avo/resources/resource_manager.rb', line 134

def get_resource_by_controller_name(name)
  valid_resources
    .find do |resource|
      resource.model_class.to_s.pluralize.underscore.tr("/", "_") == name.to_s
    end
end

#get_resource_by_model_class(klass) ⇒ Object

Returns the Avo resource by singular snake_cased name From all the resources that use the same model_class, it will fetch the first one in alphabetical order

get_resource_by_name(‘User’) => instance of Avo::Resources::User get_resource_by_name(User) => instance of Avo::Resources::User



118
119
120
121
122
123
124
125
126
127
128
# File 'lib/avo/resources/resource_manager.rb', line 118

def get_resource_by_model_class(klass)
  # Fetch the mappings imposed by the user.
  # If they are present, use those ones.
  mapping = get_mapping_for_model klass
  return get_resource(mapping) if mapping.present?

  valid_resources
    .find do |resource|
      resource.model_class.model_name.name == klass.to_s
    end
end

#get_resource_by_name(name) ⇒ Object

Returns the Avo resource by singular snake_cased name

get_resource_by_name(‘user’) => instance of Avo::Resources::User



99
100
101
# File 'lib/avo/resources/resource_manager.rb', line 99

def get_resource_by_name(name)
  get_resource name.singularize.camelize
end

#get_resource_by_plural_name(name) ⇒ Object

Returns the Avo resource by singular snake_cased name

get_resource_by_name(‘z posts’) => instance of Avo::Resources::ZPost



106
107
108
109
110
# File 'lib/avo/resources/resource_manager.rb', line 106

def get_resource_by_plural_name(name)
  resources.find do |resource|
    resource.plural_name == name
  end
end

#guess_resource(name) ⇒ Object

Returns the Avo resource by some name



142
143
144
# File 'lib/avo/resources/resource_manager.rb', line 142

def guess_resource(name)
  get_resource_by_name(name.to_s) || get_resource_by_model_class(name)
end

#resources_for_navigation(user = nil) ⇒ Object



167
168
169
170
171
172
# File 'lib/avo/resources/resource_manager.rb', line 167

def resources_for_navigation(user = nil)
  get_available_resources(user)
    .select do |resource|
      resource.visible_on_sidebar
    end
end

#valid_resourcesObject

Filters out the resources that are missing the model_class



81
82
83
# File 'lib/avo/resources/resource_manager.rb', line 81

def valid_resources
  resources.select { |resource| resource.model_class.present? }.sort_by(&:name)
end