klastera 1.4.0.1 → 1.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a400414db24740d7888bd0627051715a8b81c6d6f481e15b3819958b043a984f
4
- data.tar.gz: 782575cb6ffd02a17dc9318878bc9b3b678e98760feb936038f18dd73dd99326
3
+ metadata.gz: e524bc600751df634962778af44d6b9bd782cabdf7a125a145d2a7efbfbe6950
4
+ data.tar.gz: ab457168729e69d5f1ca94f40ea667b78e3610993eaa686998e8aa792f865db1
5
5
  SHA512:
6
- metadata.gz: c5fe5cd793facd2af1ed367485daaac3822b7f2dda768d90d5aa92e5bc2a296860585d220076de1277e4bc0b5716daa4c560f9d93cc1464ff0839fb48cfa4ba8
7
- data.tar.gz: 9c01bd79e3df23f2e514ed9aab6b7e0c544a74bde7e2e88f98e18977d8e20833815e05ea0b85d36f9e72818ffe3edf34ee8c9ced19f5d81de7b4876f22a70e98
6
+ metadata.gz: f30c250c13e081a7aebeb66fce89386638d445a92f5dd995c4855483a45efd7bf7927265980fff8ffcef7ca3e9d3f5fc53c618b05babc92464a6986a8878df84
7
+ data.tar.gz: 97007ff678bbc223506ac5fc53814c9b7363c3e45ba4f39455f73d8abdd1012bab6fd7b126b3237cc42b91fbbb6a969061c72ece12549aa1d84ae0810522a43a
@@ -8,5 +8,11 @@ module Klastera::Concerns::ClusterEntity
8
8
  end
9
9
 
10
10
  module ClassMethods
11
+ def left_join_sources_of(scope_klass)
12
+ scope_klass_arel_table = scope_klass.arel_table
13
+ scope_klass_arel_table.join(arel_table, Arel::Nodes::OuterJoin).on(
14
+ scope_klass_arel_table[:id].eq(arel_table[:entity_id]), arel_table[:entity_type].eq(scope_klass.name)
15
+ ).join_sources
16
+ end
11
17
  end
12
18
  end
@@ -14,7 +14,7 @@ module Klastera::Concerns::ClusterUser
14
14
  #
15
15
  def clusters_of(organization,and_user=nil)
16
16
  and_user_id = and_user.present? ? { users: { id: and_user } } : {}
17
- ::Cluster.eager_load(cluster_users: :user).where({ organization_id: organization }.merge(and_user_id) )
17
+ ::Cluster.eager_load(cluster_users: :user).where({ organization_id: organization }.merge(and_user_id) ).order(order: :asc)
18
18
  end
19
19
 
20
20
  ##
@@ -5,8 +5,9 @@ module Klastera
5
5
 
6
6
  extend ActiveSupport::Concern
7
7
 
8
+ UNCLUSTERED_POSITION = 9999
8
9
  UNCLUSTERED_ENTITY = 'without_cluster'.freeze
9
- KLSTR_HELPERS = %i[ cluster_user cluster_organization cluster_list cluster_scope cluster_scope_through_of user_clusters_string_list ].freeze
10
+ KLSTR_HELPERS = %i[ cluster_user cluster_organization cluster_list cluster_scope cluster_scope_through_of user_clusters_string_list cluster_scope_left_join ].freeze
10
11
 
11
12
  class << self
12
13
 
@@ -29,13 +30,15 @@ module Klastera
29
30
  if organization.is_in_cluster_mode? && user.cannot_skip_cluster_clause?
30
31
  active_record_collection = ::ClusterUser.clusters_of(organization,user)
31
32
  else
32
- active_record_collection = ::Cluster.where({ organization_id: organization })
33
+ active_record_collection = ::Cluster.where({ organization_id: organization }).order(order: :asc)
33
34
  end
34
35
 
35
36
  active_record_collection = active_record_collection.order(order: :asc)
36
37
 
37
38
  if include_unclustered && organization.optional_suborganization_mode? # For show and use modes only
38
- active_record_collection << ::Cluster.new({nid: UNCLUSTERED_ENTITY, name: I18n.t("klastera.#{UNCLUSTERED_ENTITY}")})
39
+ active_record_collection.append(
40
+ ::Cluster.new({nid: UNCLUSTERED_ENTITY, name: I18n.t("klastera.#{UNCLUSTERED_ENTITY}")}, order: UNCLUSTERED_POSITION )
41
+ )
39
42
  end
40
43
  active_record_collection
41
44
  end
@@ -76,28 +79,39 @@ module Klastera
76
79
  # cluster_filter_id is present when the optional_suborganization mode is on. BUT!
77
80
  # Be aware that if the cluster_filter is not present, the value of force_cluster_clause
78
81
  # will be overridden by the returned value of cannot_skip_cluster_clause? method.
79
- #
80
- def cluster_scope!(scope_klass, user, organization, cluster_filter=nil, force_cluster_clause=false)
81
- scope_klass = scope_class(scope_klass)
82
+ def should_clusterize_scope?(user, organization, cluster_filter=nil, force_cluster_clause=false)
83
+ should = false # I don't know if this is a good idea
82
84
  if organization.is_in_cluster_mode? && ( cluster_filter.present? || force_cluster_clause = user.cannot_skip_cluster_clause? ) # yes, this is an assignation
83
85
  cluster_ids = []
84
86
  # Set another variable as array to get the cluster id(s)
85
87
  if cluster_filter.present?
86
88
  cluster_ids = cluster_filter.is_a?(Array) ? cluster_filter : [cluster_filter]
87
89
  elsif force_cluster_clause
88
- cluster_ids = ::ClusterUser.clusters_of(organization,user).map(&:id).sort
90
+ cluster_ids = ::ClusterUser.clusters_of(organization,user).map(&:id)
89
91
  end
90
92
  # We will avoid the query unless cluster_ids is having values OR force_cluster_clause is set (see method description)
91
93
  if cluster_ids.present? || force_cluster_clause
92
- scope_klass = scope_klass.eager_load(:organization,cluster_entities: :cluster)
93
94
  # We add the unclustered if the value of cluster_filter have the special without_cluster string or as method description says
94
95
  if cluster_ids.delete(UNCLUSTERED_ENTITY) || ( force_cluster_clause && organization.optional_suborganization_mode? )
95
96
  cluster_ids << nil
96
97
  end
97
- scope_klass = scope_klass.where( cluster_entities: { cluster_id: cluster_ids } )
98
+ should = true
99
+ end
100
+ end
101
+ yield(should,cluster_ids)
102
+ end
103
+
104
+ #
105
+ # The cleanest and fast way to clusterize a entity!
106
+ #
107
+ def cluster_scope!(scope_klass, user, organization, cluster_filter=nil, force_cluster_clause=false)
108
+ scope = scope_class(scope_klass)
109
+ should_clusterize_scope?(user,organization,cluster_filter,force_cluster_clause) do |should,cluster_ids|
110
+ if should
111
+ scope = scope.eager_load(:organization,cluster_entities: :cluster).where( cluster_entities: { cluster_id: cluster_ids } )
98
112
  end
99
113
  end
100
- scope_klass.where(organization_id: organization)
114
+ scope.where(organization_id: organization)
101
115
  end
102
116
 
103
117
 
@@ -107,7 +121,7 @@ module Klastera
107
121
  unclusterized_scope = scope_class(scope_klass)
108
122
 
109
123
  if organization.is_in_cluster_mode? && ( force_cluster_clause || user.cannot_skip_cluster_clause? )
110
- unclusterized_scope = unclusterized_scope.joins(relation => :cluster_entities)
124
+ unclusterized_scope = unclusterized_scope.joins(relation).joins(Klastera::ClusterEntity.left_join_sources_of(cluster_entity_klass))
111
125
  end
112
126
 
113
127
  if scope_klass.respond_to?(:organization)
@@ -117,22 +131,51 @@ module Klastera
117
131
  unclusterized_scope.where("#{relation}_id" => cluster_scope!(cluster_entity_klass, user, organization, cluster_filter, force_cluster_clause))
118
132
  end
119
133
 
120
- # 
134
+ #
121
135
  # Returns an array with a clusterized scoped result and its grouped version
122
136
  #
123
137
  def group_by_cluster_scope!(scope_klass, user, organization, cluster_filter=[], scope_scopes=[])
124
138
  cluster_ids = cluster_filter.is_a?(Array) ? cluster_filter : [cluster_filter]
125
- kluster_scope = cluster_scope!(scope_klass, user, organization, cluster_ids, organization.optional_suborganization_mode? )
139
+ kluster_scope = cluster_scope!(scope_klass, user, organization, cluster_ids, organization.is_in_cluster_mode? )
140
+
126
141
  scope_scopes.each do |tuple_scope|
127
142
  scope_name, scope_arg = tuple_scope
128
143
  kluster_scope = scope_arg.present? ? kluster_scope.send(scope_name,scope_arg) : kluster_scope.send(scope_name)
129
144
  end
130
- [
131
- kluster_scope,
132
- kluster_scope.order(:cluster_id).group_by do |e|
133
- e.cluster.present? ? e.cluster.name : I18n.t("klastera.#{UNCLUSTERED_ENTITY}")
145
+
146
+ group_by_block = ->(o) {
147
+ if organization.is_in_cluster_mode?
148
+ o.cluster.present? ? o.cluster.name : UNCLUSTERED_POSITION
149
+ else
150
+ I18n.t("klastera.group_by_cluster_scope.#{scope_klass.model_name.plural}")
151
+ end
152
+ }
153
+
154
+ grouped_cluster_scope = kluster_scope.group_by(&group_by_block).sort_by{|k,v|k.to_s}
155
+
156
+ grouped_cluster_scope.dup.each do |group|
157
+ if group.first == UNCLUSTERED_POSITION
158
+ grouped_cluster_scope.delete(group)
159
+ group[0] = I18n.t("klastera.#{UNCLUSTERED_ENTITY}")
160
+ grouped_cluster_scope.append(group)
134
161
  end
135
- ]
162
+ end
163
+
164
+ [ kluster_scope, grouped_cluster_scope ]
165
+ end
166
+
167
+ #
168
+ # A helper that returns a CLUSTER SCOPE to build queries that need explicit LEFT OUTER JOIN clause,
169
+ # instead of the default INNER JOIN provide by ActiveRecord's joins method
170
+ #
171
+ def cluster_scope_left_join!(scope_klass,organization)
172
+ cluster_entities_arel_table = Klastera::ClusterEntity.arel_table
173
+ cluster_arel_table = ::Cluster.arel_table
174
+ cluster_entities_cluster = cluster_entities_arel_table.join(cluster_arel_table, Arel::Nodes::OuterJoin).on(
175
+ cluster_entities_arel_table[:cluster_id].eq(cluster_arel_table[:id]),
176
+ ).join_sources
177
+
178
+ scope_class(scope_klass).where(organization_id: organization).joins(Klastera::ClusterEntity.left_join_sources_of(scope_klass)).joins(cluster_entities_cluster)
136
179
  end
137
180
  end
138
181
 
@@ -175,6 +218,10 @@ module Klastera
175
218
  Klastera.user_clusters_string_list!(cluster_user, cluster_organization, object_entity.try(:cluster_entities), separator, attribute)
176
219
  end
177
220
 
221
+ def cluster_scope_left_join(scope_klass)
222
+ Klastera.cluster_scope_left_join!(scope_klas,cluster_organization)
223
+ end
224
+
178
225
  included do
179
226
  Klastera::KLSTR_HELPERS.each do |action|
180
227
  if respond_to?(:helper_method)
@@ -1,3 +1,3 @@
1
1
  module Klastera
2
- VERSION = "1.4.0.1"
2
+ VERSION = "1.4.3"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: klastera
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0.1
4
+ version: 1.4.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gino Barahona
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-30 00:00:00.000000000 Z
11
+ date: 2020-08-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -127,7 +127,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
127
127
  - !ruby/object:Gem::Version
128
128
  version: '0'
129
129
  requirements: []
130
- rubygems_version: 3.0.8
130
+ rubygems_version: 3.1.2
131
131
  signing_key:
132
132
  specification_version: 4
133
133
  summary: Clusterization Engine