module Klastera

Constants

KLSTR_HELPERS
UNCLUSTERED_ENTITY
UNCLUSTERED_POSITION
VERSION

Public Class Methods

cluster_list!(organization,user,include_unclustered=true) click to toggle source

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
cluster_scope!(scope_klass, user, organization, cluster_filter=nil, force_cluster_clause=false) click to toggle source

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
cluster_scope_left_join!(scope_klass,organization) click to toggle source

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
cluster_scope_through_of!(relation, cluster_entity_klass, scope_klass, user, organization, cluster_filter=nil, force_cluster_clause=false) click to toggle source

 

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
entity_clusters_string_list!(cluster_entities,separator,attribute=:name,allowed_cluster_ids=nil) click to toggle source

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
group_by_cluster_scope!(scope_klass, user, organization, cluster_filter=[], scope_scopes=[]) click to toggle source

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
scope_class(object) click to toggle source
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
should_clusterize_scope?(user, organization, cluster_filter=nil, force_cluster_clause=false) { |should,cluster_ids| ... } click to toggle source

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
user_clusters_string_list!(user,organization,cluster_entities,separator,attribute=:name) click to toggle source

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

cluster_list(include_unclustered=true) click to toggle source
# File lib/klastera.rb, line 201
def cluster_list(include_unclustered=true)
  Klastera.cluster_list!(cluster_organization, cluster_user, include_unclustered)
end
cluster_organization() click to toggle source
# File lib/klastera.rb, line 188
def cluster_organization
  current_organization
end
cluster_scope(scope_klass, cluster_filter=nil, force_cluster_clause=false) click to toggle source
# 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) click to toggle source
# 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) click to toggle source
# 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() click to toggle source
# File lib/klastera.rb, line 184
def cluster_user
  current_user
end
group_by_cluster_scope(scope_klass, cluster_filter=[], scope_scopes=[]) click to toggle source
# 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() click to toggle source
# 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) click to toggle source
# 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