module Klastera
Constants
- KLSTR_HELPERS
- UNCLUSTERED_ENTITY
- UNCLUSTERED_POSITION
- VERSION
Public Class Methods
Returns which clusters a user can see avoiding unnecessary queries if the cluster restraint doesn't apply
# 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
The cleanest and fast way to clusterize a entity!
# 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
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
# 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
Filter non-clustered entity through a clusterized one
# 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
Return a string with cluster attribute separated by separator argument A array of cluster ids can be passed fo filter the result
# 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
Returns an array with a clusterized scoped result and its grouped version
# 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, 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
TODO: Implement a validation to ensure that
object is a ActiveRecord::Base class
(or just try to guess how to retrieve the argument class)
# File lib/klastera.rb, line 21 def scope_class(object) object end
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.
# 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
cluster_list
! needs a user and a organization. that why we perfomed this logic here
# 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
Public Instance Methods
# File lib/klastera.rb, line 201 def cluster_list(include_unclustered=true) Klastera.cluster_list!(cluster_organization, cluster_user, include_unclustered) end
# File lib/klastera.rb, line 188 def cluster_organization current_organization end
# 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
# File lib/klastera.rb, line 221 def cluster_scope_left_join(scope_klass) Klastera.cluster_scope_left_join!(scope_klas,cluster_organization) end
# 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
# File lib/klastera.rb, line 184 def cluster_user current_user end
# 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
# 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
# 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