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



144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/avo/resources/resource_manager.rb', line 144

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



140
141
142
# File 'lib/avo/resources/resource_manager.rb', line 140

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



125
126
127
128
129
130
# File 'lib/avo/resources/resource_manager.rb', line 125

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



109
110
111
112
113
114
115
116
117
118
119
# File 'lib/avo/resources/resource_manager.rb', line 109

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

#guess_resource(name) ⇒ Object

Returns the Avo resource by some name



133
134
135
# File 'lib/avo/resources/resource_manager.rb', line 133

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

#resources_for_navigation(user = nil) ⇒ Object



158
159
160
161
162
163
# File 'lib/avo/resources/resource_manager.rb', line 158

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