Class: Decidim::ActionLog

Inherits:
ApplicationRecord show all
Includes:
ScopableParticipatorySpace
Defined in:
decidim-core/app/models/decidim/action_log.rb

Overview

This class represents an action of a user on a resource. It is used for transparency reasons, to log all actions so all other users can see the actions being performed.

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.for_adminObject

A scope that filters all the logs that should be visible at the admin panel.


48
49
50
# File 'decidim-core/app/models/decidim/action_log.rb', line 48

def self.for_admin
  where(visibility: %w(admin-only all))
end

.lazy_relation(id_method, klass_name, cache) ⇒ Object

Returns a Batchloader for a given class to avoid N+1 queries.

Since ActionLogs are related to many different resources, loading a collection of them would trigger a lot of N+1 queries. We're using BatchLoader to accumulate and group all the resource by their class and only loading them when it's necessary.


111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'decidim-core/app/models/decidim/action_log.rb', line 111

def self.lazy_relation(id_method, klass_name, cache)
  klass = klass_name.constantize
  BatchLoader.for(id_method).batch(cache: cache, key: klass.name.underscore) do |relation_ids, loader|
    scope = klass.where(id: relation_ids)

    scope = if klass.include?(Decidim::HasComponent)
              scope.where(id: relation_ids).includes(:component).where.not(decidim_components: { published_at: nil })
            elsif klass.reflect_on_association(:organization)
              scope.where(id: relation_ids).includes(:organization)
            elsif klass_name == "Decidim::Comments::Comment"
              scope.where(id: relation_ids).includes([:moderation, :root_commentable, :user_group])
            else
              scope
            end

    scope = scope.published if klass.include?(Decidim::Publicable)

    scope.each { |relation| loader.call(relation.id, relation) }
  end
end

Instance Method Details

#component_lazy(cache: true) ⇒ Object

Lazy loads the `component` association through BatchLoader, can be used as a regular object.


61
62
63
# File 'decidim-core/app/models/decidim/action_log.rb', line 61

def component_lazy(cache: true)
  self.class.lazy_relation(decidim_component_id, "Decidim::Component", cache)
end

#log_presenter_class_for(log_type) ⇒ Object

Public: Finds the correct presenter class for the given `log_type` and the related `resource_type`. If no specific presenter can be found, it falls back to `Decidim::Log::BasePresenter`

log_type - a Symbol representing the log

Returns a Class.


99
100
101
102
103
# File 'decidim-core/app/models/decidim/action_log.rb', line 99

def log_presenter_class_for(log_type)
  resource_type.constantize.log_presenter_class_for(log_type)
rescue NameError
  Decidim::Log::BasePresenter
end

#organization_lazy(cache: true) ⇒ Object

Lazy loads the `organization` association through BatchLoader, can be used as a regular object.


67
68
69
# File 'decidim-core/app/models/decidim/action_log.rb', line 67

def organization_lazy(cache: true)
  self.class.lazy_relation(decidim_organization_id, "Decidim::Organization", cache)
end

#participatory_space_lazy(cache: true) ⇒ Object

Lazy loads the `participatory_space` association through BatchLoader, can be used as a regular object.


79
80
81
82
83
84
# File 'decidim-core/app/models/decidim/action_log.rb', line 79

def participatory_space_lazy(cache: true)
  return if participatory_space_id.blank? || participatory_space_type.blank?
  return resouce_lazy if participatory_space_id == resource_id && participatory_space_type == resource_type

  self.class.lazy_relation(participatory_space_id, participatory_space_type, cache)
end

#readonly?Boolean

Overwrites the method so that records cannot be modified.

Returns a Boolean.

Returns:

  • (Boolean)

55
56
57
# File 'decidim-core/app/models/decidim/action_log.rb', line 55

def readonly?
  !new_record?
end

#resource_lazy(cache: true) ⇒ Object

Lazy loads the `resource` association through BatchLoader, can be used as a regular object.


88
89
90
# File 'decidim-core/app/models/decidim/action_log.rb', line 88

def resource_lazy(cache: true)
  self.class.lazy_relation(resource_id, resource_type, cache)
end

#user_lazy(cache: true) ⇒ Object

Lazy loads the `user` association through BatchLoader, can be used as a regular object.


73
74
75
# File 'decidim-core/app/models/decidim/action_log.rb', line 73

def user_lazy(cache: true)
  self.class.lazy_relation(decidim_user_id, "Decidim::User", cache)
end

#visible_for?(user) ⇒ Boolean

Whether this activity or log is visible for a given user (can also be nil)

Returns a True/False.

Returns:

  • (Boolean)

135
136
137
138
139
140
141
142
# File 'decidim-core/app/models/decidim/action_log.rb', line 135

def visible_for?(user)
  return false if resource_lazy.blank?
  return false if participatory_space_lazy.blank?
  return false if resource_lazy.respond_to?(:hidden?) && resource_lazy.hidden?
  return false if resource_lazy.respond_to?(:can_participate?) && !resource_lazy.can_participate?(user)

  true
end