klastera 1.4.0.2 → 1.4.4

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: 2c6ed8465fe9fcf78e96af1ad4d137ecdc867cc26242e0c4aada31557668b5db
4
- data.tar.gz: 045d77f5c652c11aa1badd03c404c26b07a04ddd8d7bd7886b72ba47195d9339
3
+ metadata.gz: c15103fa238ee96065a307c2e8e4d30e99488174d0c1f6cd47cf76752998e37c
4
+ data.tar.gz: e6d79698657b081437e62238c3925e5346a4b47b17f5e4671f11bfeb7f6806a8
5
5
  SHA512:
6
- metadata.gz: 70bb42f25ded9aa221049e3d2fc25a88eb467514f562a99b5ffbc26e575a9bbf692e41af450201d82f00452f7d924e5b4f3a71409539d091ab60397de65fc379
7
- data.tar.gz: 53e3902628bfac1f1353e0d6760483df4d82a51aa4ee32066c579e23b81bdb3832ab3ef9fc79ccff94d576971958ca4d00a8920ed7860ba7df1356c894b3c2c4
6
+ metadata.gz: 3e39ddb9802da7ed9f31e320e8ac36f5f26cb2fe8a4d09065c5de22fee3851e7593b08cd7223455dfdf19a718d63a98610269c2c9702e51160834938181f47d7
7
+ data.tar.gz: 2a2f371d207ce603d3887a86cedabe5451d3edc056b5549361c46dfa0ed8a0c64aa7e4897251db7683457880c5b2868f374067690a5a9c5d34c0f92f3863f32f
@@ -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 }.order(order: :asc).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
  ##
@@ -1,6 +1,9 @@
1
1
  module Klastera::Concerns::Clusterizable
2
2
  extend ActiveSupport::Concern
3
+
3
4
  included do
5
+ class MutipleClustersOperationError < StandardError; end
6
+
4
7
  belongs_to :cluster
5
8
 
6
9
  has_many :cluster_entities, as: :entity, class_name: Klastera::ClusterEntity
@@ -18,6 +21,10 @@ module Klastera::Concerns::Clusterizable
18
21
  end
19
22
  end
20
23
 
24
+ def allow_multiple_clusters?(default=:one)
25
+ organization.cluster_cardinality_of(self.class, default: default) == :many
26
+ end
27
+
21
28
  ##
22
29
  # This is a legacy method and we don't recommend using it.
23
30
  # Implement directly Klastera.entity_clusters_string_list instead of this method.
@@ -1,7 +1,7 @@
1
1
  module Klastera::Concerns::Organization
2
2
  extend ActiveSupport::Concern
3
3
  included do
4
-
4
+ serialize :cluster_config
5
5
  has_many :clusters
6
6
 
7
7
  validates :use_cluster_as, inclusion: { in: ::Cluster::MODES.map{|m|m.to_s}, message: I18n.t('klastera.clusters.wrong_option') }, if: proc{ use_cluster_as.present? }
@@ -11,6 +11,17 @@ module Klastera::Concerns::Organization
11
11
  self.use_cluster_as.to_s.to_sym
12
12
  end
13
13
 
14
+ def cluster_cardinality_of(entity, default: :many)
15
+ if cluster_config.is_a?(Hash)
16
+ entities_cardinality = cluster_config[:entities]&.[](:cardinality)||{}
17
+ entity = entity.to_s.to_sym
18
+ if entities_cardinality.has_key?(entity)
19
+ default = entities_cardinality[entity]
20
+ end
21
+ end
22
+ default.to_s.to_sym
23
+ end
24
+
14
25
  ##
15
26
  # Return a boolean if one of three of options was set in organization
16
27
  # As useless option you can retrieve the value passing false as argument.
@@ -0,0 +1,5 @@
1
+ class AddClusterConfigToOrganization < ActiveRecord::Migration
2
+ def change
3
+ add_column :organizations, :cluster_config, :text
4
+ end
5
+ end
@@ -7,7 +7,7 @@ module Klastera
7
7
 
8
8
  UNCLUSTERED_POSITION = 9999
9
9
  UNCLUSTERED_ENTITY = 'without_cluster'.freeze
10
- 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
11
11
 
12
12
  class << self
13
13
 
@@ -79,9 +79,8 @@ module Klastera
79
79
  # cluster_filter_id is present when the optional_suborganization mode is on. BUT!
80
80
  # Be aware that if the cluster_filter is not present, the value of force_cluster_clause
81
81
  # will be overridden by the returned value of cannot_skip_cluster_clause? method.
82
- #
83
- def cluster_scope!(scope_klass, user, organization, cluster_filter=nil, force_cluster_clause=false)
84
- 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
85
84
  if organization.is_in_cluster_mode? && ( cluster_filter.present? || force_cluster_clause = user.cannot_skip_cluster_clause? ) # yes, this is an assignation
86
85
  cluster_ids = []
87
86
  # Set another variable as array to get the cluster id(s)
@@ -92,15 +91,27 @@ module Klastera
92
91
  end
93
92
  # We will avoid the query unless cluster_ids is having values OR force_cluster_clause is set (see method description)
94
93
  if cluster_ids.present? || force_cluster_clause
95
- scope_klass = scope_klass.eager_load(:organization,cluster_entities: :cluster)
96
94
  # We add the unclustered if the value of cluster_filter have the special without_cluster string or as method description says
97
95
  if cluster_ids.delete(UNCLUSTERED_ENTITY) || ( force_cluster_clause && organization.optional_suborganization_mode? )
98
96
  cluster_ids << nil
99
97
  end
100
- scope_klass = scope_klass.where( cluster_entities: { cluster_id: cluster_ids } )
98
+ should = true
101
99
  end
102
100
  end
103
- scope_klass.where(organization_id: organization)
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 } )
112
+ end
113
+ end
114
+ scope.where(organization_id: organization)
104
115
  end
105
116
 
106
117
 
@@ -110,7 +121,7 @@ module Klastera
110
121
  unclusterized_scope = scope_class(scope_klass)
111
122
 
112
123
  if organization.is_in_cluster_mode? && ( force_cluster_clause || user.cannot_skip_cluster_clause? )
113
- 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))
114
125
  end
115
126
 
116
127
  if scope_klass.respond_to?(:organization)
@@ -152,6 +163,20 @@ module Klastera
152
163
 
153
164
  [ kluster_scope, grouped_cluster_scope ]
154
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)
179
+ end
155
180
  end
156
181
 
157
182
  ##################################################################################################################################################
@@ -193,6 +218,10 @@ module Klastera
193
218
  Klastera.user_clusters_string_list!(cluster_user, cluster_organization, object_entity.try(:cluster_entities), separator, attribute)
194
219
  end
195
220
 
221
+ def cluster_scope_left_join(scope_klass)
222
+ Klastera.cluster_scope_left_join!(scope_klas,cluster_organization)
223
+ end
224
+
196
225
  included do
197
226
  Klastera::KLSTR_HELPERS.each do |action|
198
227
  if respond_to?(:helper_method)
@@ -1,3 +1,3 @@
1
1
  module Klastera
2
- VERSION = "1.4.0.2"
2
+ VERSION = "1.4.4"
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.2
4
+ version: 1.4.4
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-31 00:00:00.000000000 Z
11
+ date: 2020-09-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -93,6 +93,7 @@ files:
93
93
  - db/migrate/20200330010551_create_klastera_cluster_users.rb
94
94
  - db/migrate/20200330221601_add_order_field_to_clusters.rb
95
95
  - db/migrate/20200518142609_create_klastera_cluster_entities.rb
96
+ - db/migrate/20200908180057_add_cluster_config_to_organization.rb
96
97
  - lib/klastera.rb
97
98
  - lib/klastera/engine.rb
98
99
  - lib/klastera/version.rb