Module: Klastera
- Extended by:
- ActiveSupport::Concern
- Defined in:
- lib/klastera.rb,
lib/klastera/engine.rb,
lib/klastera/version.rb,
app/models/klastera/cluster.rb,
app/models/klastera/transfer.rb,
app/models/klastera/cluster_user.rb,
app/models/klastera/cluster_entity.rb,
app/models/klastera/cluster_filter.rb,
app/helpers/klastera/application_helper.rb,
app/controllers/klastera/clusters_controller.rb,
app/controllers/klastera/application_controller.rb
Defined Under Namespace
Modules: ApplicationHelper Classes: ApplicationController, Cluster, ClusterEntity, ClusterFilter, ClusterUser, ClustersController, Engine, Transfer
Constant Summary collapse
- UNCLUSTERED_POSITION =
9999
- UNCLUSTERED_ENTITY =
'without_cluster'.freeze
- KLSTR_HELPERS =
%i[ cluster_user cluster_organization cluster_list cluster_scope cluster_scope_through_of user_clusters_string_list cluster_scope_left_join ].freeze
- VERSION =
"1.5.4"
Class Method Summary collapse
-
.cluster_list!(organization, user, include_unclustered = true) ⇒ Object
Returns which clusters a user can see avoiding unnecessary queries if the cluster restraint doesn’t apply.
-
.cluster_scope!(scope_klass, user, organization, cluster_filter = nil, force_cluster_clause = false) ⇒ Object
The cleanest and fast way to clusterize a entity!.
-
.cluster_scope_left_join!(scope_klass, organization) ⇒ Object
A helper that returns a CLUSTER SCOPE to build queries that need explicit LEFT OUTER JOIN clause, instead of the default INNER JOIN provide by ActiveRecord’s joins method.
-
.cluster_scope_through_of!(relation, cluster_entity_klass, scope_klass, user, organization, cluster_filter = nil, force_cluster_clause = false) ⇒ Object
Filter non-clustered entity through a clusterized one.
-
.entity_clusters_string_list!(cluster_entities, separator, attribute = :name, allowed_cluster_ids = nil) ⇒ Object
Return a string with cluster attribute separated by separator argument A array of cluster ids can be passed fo filter the result.
-
.group_by_cluster_scope!(scope_klass, user, organization, cluster_filter = [], scope_scopes = []) ⇒ Object
Returns an array with a clusterized scoped result and its grouped version.
-
.scope_class(object) ⇒ Object
TODO: Implement a validation to ensure that object is a ActiveRecord::Base class (or just try to guess how to retrieve the argument class).
-
.should_clusterize_scope?(user, organization, cluster_filter = nil, force_cluster_clause = false) {|should, cluster_ids| ... } ⇒ Boolean
We will try to avoid cluster clause except when: 1.- cluster mode is active AND 2a.- cluster_filter is present (someone wants to filter by cluster) OR 2b.- the current user has some limitations and must checks they cluster relation - User is having clusters in optional_suborganization mode - User IS NOT having clusters in required_suborganization mode.
-
.user_clusters_string_list!(user, organization, cluster_entities, separator, attribute = :name) ⇒ Object
cluster_list! needs a user and a organization.
Instance Method Summary collapse
- #cluster_list(include_unclustered = true) ⇒ Object
- #cluster_organization ⇒ Object
- #cluster_scope(scope_klass, cluster_filter = nil, force_cluster_clause = false) ⇒ Object
- #cluster_scope_left_join(scope_klass) ⇒ Object
- #cluster_scope_through_of(relation, cluster_entity_klass, scope_klass, cluster_filter = nil, force_cluster_clause = false) ⇒ Object
- #cluster_user ⇒ Object
- #group_by_cluster_scope(scope_klass, cluster_filter = [], scope_scopes = []) ⇒ Object
- #set_cluster_filter ⇒ Object
- #user_clusters_string_list(object_entity, separator, attribute = :name) ⇒ Object
Class Method Details
.cluster_list!(organization, user, include_unclustered = true) ⇒ Object
Returns which clusters a user can see avoiding unnecessary queries if the cluster restraint doesn’t apply
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/klastera.rb', line 28 def cluster_list!(organization,user,include_unclustered=true) # Only the cluster mode on and the mandatory user-cluster relation will use a join clause to get the clusters list if organization.is_in_cluster_mode? && user.cannot_skip_cluster_clause? active_record_collection = ::ClusterUser.clusters_of(organization,user) else active_record_collection = ::Cluster.where({ organization_id: organization }).order(order: :asc) end active_record_collection = active_record_collection.order(order: :asc) if include_unclustered && organization.optional_suborganization_mode? # For show and use modes only active_record_collection.to_a.append( ::Cluster.new({nid: UNCLUSTERED_ENTITY, name: I18n.t("klastera.#{UNCLUSTERED_ENTITY}"), order: UNCLUSTERED_POSITION }) ) end active_record_collection end |
.cluster_scope!(scope_klass, user, organization, cluster_filter = nil, force_cluster_clause = false) ⇒ Object
The cleanest and fast way to clusterize a entity!
107 108 109 110 111 112 113 114 115 |
# File 'lib/klastera.rb', line 107 def cluster_scope!(scope_klass, user, organization, cluster_filter=nil, force_cluster_clause=false) scope = scope_class(scope_klass) should_clusterize_scope?(user,organization,cluster_filter,force_cluster_clause) do |should,cluster_ids| if should scope = scope.eager_load(:organization,cluster_entities: :cluster).where( cluster_entities: { cluster_id: cluster_ids } ) end end scope.where(organization_id: organization) end |
.cluster_scope_left_join!(scope_klass, organization) ⇒ Object
A helper that returns a CLUSTER SCOPE to build queries that need explicit LEFT OUTER JOIN clause, instead of the default INNER JOIN provide by ActiveRecord’s joins method
171 172 173 174 175 176 177 178 179 |
# File 'lib/klastera.rb', line 171 def cluster_scope_left_join!(scope_klass,organization) cluster_entities_arel_table = Klastera::ClusterEntity.arel_table cluster_arel_table = ::Cluster.arel_table cluster_entities_cluster = cluster_entities_arel_table.join(cluster_arel_table, Arel::Nodes::OuterJoin).on( cluster_entities_arel_table[:cluster_id].eq(cluster_arel_table[:id]), ).join_sources scope_class(scope_klass).where(organization_id: organization).joins(Klastera::ClusterEntity.left_join_sources_of(scope_klass)).joins(cluster_entities_cluster) end |
.cluster_scope_through_of!(relation, cluster_entity_klass, scope_klass, user, organization, cluster_filter = nil, force_cluster_clause = false) ⇒ Object
Filter non-clustered entity through a clusterized one
120 121 122 123 124 125 126 127 128 129 130 131 132 |
# File 'lib/klastera.rb', line 120 def cluster_scope_through_of!(relation, cluster_entity_klass, scope_klass, user, organization, cluster_filter=nil, force_cluster_clause=false) unclusterized_scope = scope_class(scope_klass) if organization.is_in_cluster_mode? && ( force_cluster_clause || user.cannot_skip_cluster_clause? ) unclusterized_scope = unclusterized_scope.joins(relation).joins(Klastera::ClusterEntity.left_join_sources_of(cluster_entity_klass)) end if scope_klass.respond_to?(:organization) unclusterized_scope = unclusterized_scope.where(organization_id: organization) end unclusterized_scope.where("#{relation}_id" => cluster_scope!(cluster_entity_klass, user, organization, cluster_filter, force_cluster_clause)) end |
.entity_clusters_string_list!(cluster_entities, separator, attribute = :name, allowed_cluster_ids = nil) ⇒ Object
Return a string with cluster attribute separated by separator argument A array of cluster ids can be passed fo filter the result
50 51 52 53 54 55 56 57 58 |
# File 'lib/klastera.rb', line 50 def entity_clusters_string_list!(cluster_entities,separator,attribute=:name,allowed_cluster_ids=nil) _cluster_entities = cluster_entities.reject(&:nil?) if allowed_cluster_ids.is_a?(Array) _cluster_entities.select!{|ce| allowed_cluster_ids.include?(ce.cluster_id)} end _cluster_entities.map do |ce| ce.cluster.try(attribute) end.compact.sort.join(separator) end |
.group_by_cluster_scope!(scope_klass, user, organization, cluster_filter = [], scope_scopes = []) ⇒ Object
Returns an array with a clusterized scoped result and its grouped version
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
# File 'lib/klastera.rb', line 137 def group_by_cluster_scope!(scope_klass, user, organization, cluster_filter=[], scope_scopes=[]) cluster_ids = cluster_filter.is_a?(Array) ? cluster_filter : [cluster_filter] kluster_scope = cluster_scope!(scope_klass, user, organization, cluster_ids.compact, organization.is_in_cluster_mode? ) scope_scopes.each do |tuple_scope| scope_name, scope_arg = tuple_scope kluster_scope = scope_arg.present? ? kluster_scope.send(scope_name,scope_arg) : kluster_scope.send(scope_name) end group_by_block = ->(o) { if organization.is_in_cluster_mode? o.cluster.present? ? o.cluster.name : UNCLUSTERED_POSITION else I18n.t("klastera.group_by_cluster_scope.#{scope_klass.model_name.plural}") end } grouped_cluster_scope = kluster_scope.group_by(&group_by_block).sort_by{|k,v|k.to_s} grouped_cluster_scope.dup.each do |group| if group.first == UNCLUSTERED_POSITION grouped_cluster_scope.delete(group) group[0] = I18n.t("klastera.#{UNCLUSTERED_ENTITY}") grouped_cluster_scope.append(group) end end [ kluster_scope, grouped_cluster_scope ] end |
.scope_class(object) ⇒ Object
TODO: Implement a validation to ensure that object is a ActiveRecord::Base class (or just try to guess how to retrieve the argument class)
21 22 23 |
# File 'lib/klastera.rb', line 21 def scope_class(object) object end |
.should_clusterize_scope?(user, organization, cluster_filter = nil, force_cluster_clause = false) {|should, cluster_ids| ... } ⇒ Boolean
We will try to avoid cluster clause except when: 1.- cluster mode is active AND
2a.- cluster_filter is present (someone wants to filter by cluster)
OR
2b.- the current user has some limitations and must checks they cluster relation
- User is having clusters in optional_suborganization mode
- User IS NOT having clusters in required_suborganization mode
For the other hand, with force_cluster_clause we can skip the previous logic if cluster_filter_id is present when the optional_suborganization mode is on. BUT! Be aware that if the cluster_filter is not present, the value of force_cluster_clause will be overridden by the returned value of cannot_skip_cluster_clause? method.
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/klastera.rb', line 82 def should_clusterize_scope?(user, organization, cluster_filter=nil, force_cluster_clause=false) should = false # I don't know if this is a good idea if organization.is_in_cluster_mode? && ( cluster_filter.present? || force_cluster_clause = user.cannot_skip_cluster_clause? ) # yes, this is an assignation cluster_ids = [] # Set another variable as array to get the cluster id(s) if cluster_filter.present? cluster_ids = cluster_filter.is_a?(Array) ? cluster_filter : [cluster_filter] elsif force_cluster_clause cluster_ids = ::ClusterUser.clusters_of(organization,user).map(&:id) end # We will avoid the query unless cluster_ids is having values OR force_cluster_clause is set (see method description) if cluster_ids.present? || force_cluster_clause # We add the unclustered if the value of cluster_filter have the special without_cluster string or as method description says if cluster_ids.delete(UNCLUSTERED_ENTITY) || ( force_cluster_clause && organization.optional_suborganization_mode? ) cluster_ids << nil end should = true end end yield(should,cluster_ids) end |
.user_clusters_string_list!(user, organization, cluster_entities, separator, attribute = :name) ⇒ Object
cluster_list! needs a user and a organization. that why we perfomed this logic here
63 64 65 66 |
# File 'lib/klastera.rb', line 63 def user_clusters_string_list!(user,organization,cluster_entities,separator,attribute=:name) @clusters_session ||= Klastera.cluster_list!(organization,user) self.entity_clusters_string_list!(cluster_entities, separator, attribute, @clusters_session.map(&:id)) end |
Instance Method Details
#cluster_list(include_unclustered = true) ⇒ Object
201 202 203 |
# File 'lib/klastera.rb', line 201 def cluster_list(include_unclustered=true) Klastera.cluster_list!(cluster_organization, cluster_user, include_unclustered) end |
#cluster_organization ⇒ Object
188 189 190 |
# File 'lib/klastera.rb', line 188 def cluster_organization current_organization end |
#cluster_scope(scope_klass, cluster_filter = nil, force_cluster_clause = false) ⇒ Object
205 206 207 |
# File 'lib/klastera.rb', line 205 def cluster_scope(scope_klass, cluster_filter=nil, force_cluster_clause=false) Klastera.cluster_scope!(scope_klass, cluster_user, cluster_organization, cluster_filter, force_cluster_clause) end |
#cluster_scope_left_join(scope_klass) ⇒ Object
221 222 223 |
# File 'lib/klastera.rb', line 221 def cluster_scope_left_join(scope_klass) Klastera.cluster_scope_left_join!(scope_klas,cluster_organization) end |
#cluster_scope_through_of(relation, cluster_entity_klass, scope_klass, cluster_filter = nil, force_cluster_clause = false) ⇒ Object
209 210 211 |
# File 'lib/klastera.rb', line 209 def cluster_scope_through_of(relation, cluster_entity_klass, scope_klass, cluster_filter=nil, force_cluster_clause=false) Klastera.cluster_scope_through_of!(relation, cluster_entity_klass, scope_klass, cluster_user, cluster_organization, cluster_filter, force_cluster_clause) end |
#cluster_user ⇒ Object
184 185 186 |
# File 'lib/klastera.rb', line 184 def cluster_user current_user end |
#group_by_cluster_scope(scope_klass, cluster_filter = [], scope_scopes = []) ⇒ Object
213 214 215 |
# File 'lib/klastera.rb', line 213 def group_by_cluster_scope(scope_klass, cluster_filter=[], scope_scopes=[]) Klastera.group_by_cluster_scope!(scope_klass, cluster_user, cluster_organization, cluster_filter, scope_scopes) end |
#set_cluster_filter ⇒ Object
192 193 194 195 196 197 198 199 |
# File 'lib/klastera.rb', line 192 def set_cluster_filter cluster_filter_params = params.require(:cluster_filter) rescue {} @cluster_filter = ::ClusterFilter.new( cluster_filter_params.present? ? cluster_filter_params.permit( [ :cluster_id ].concat( ::ClusterFilter.attributes ) ) : {} ) end |
#user_clusters_string_list(object_entity, separator, attribute = :name) ⇒ Object
217 218 219 |
# File 'lib/klastera.rb', line 217 def user_clusters_string_list(object_entity, separator, attribute=:name) Klastera.user_clusters_string_list!(cluster_user, cluster_organization, object_entity.try(:cluster_entities), separator, attribute) end |