klastera 1.2.2 → 1.2.4.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5ca95ff5ffe21289a12131f7090036072103e196af1d81f9110c7896d705f837
4
- data.tar.gz: c026cb690ec0fdbad89237a64e837b74e5112c50b4339dc78e3bdce03dfd84d5
3
+ metadata.gz: 8780a6928f5249deb34be42cac1f52a226113865b9f29ddb12e1a36f018141ed
4
+ data.tar.gz: 1d99b709cea49a08533192ad8a1df621d78ea4d4ee59e1c266f06e952e6d8063
5
5
  SHA512:
6
- metadata.gz: 1f71455ad531a02b1f46672644f8d77aa98a4c842121de8fa1539e26920690d103e997a22470ea5dfa0efdbce6a970a89a824324343b87d90546aa4ad3653e5b
7
- data.tar.gz: 1d5962c2c598cc389c67306fcd8bbf10ca7577c07bc89795daf98d774537bac01ddcdbd366c2478a4cfc0ea3b3b9082dd1c20edcf0e58e481d7461b92c71c372
6
+ metadata.gz: 62c72441e00d9edb6c17525453cde71d864389c9342dbe54df3538609814aef0cdcbc3f7c49f49134d526e2da1f99ff1cc258b750cd024a7031afd3a80977d2d
7
+ data.tar.gz: 806978a3fae34b0a2ddda331ce37b90de2e66f9c77bd707859b721ac7c83980f706b5eb432a00875db8b26b4c8901b11307ef62ab063952d013eef30eca69772
@@ -9,9 +9,10 @@ module Klastera::Concerns::Clusterizable
9
9
 
10
10
  validates :cluster_id, presence: true, if: proc { self.try(:cluster_id) && self.organization.required_suborganization_mode? }
11
11
  validate :at_least_one_cluster_entity, if: proc { self.organization.required_suborganization_mode? }
12
+ validate :uniqueness_of_cluster_entity_record
12
13
 
13
14
  scope :related_clusters, ->() {
14
- includes(:cluster_entities).where("cluster_entities.entity_id = #{self.table_name}.id")
15
+ joins(:cluster_entities).where("cluster_entities.entity_id = #{self.table_name}.id")
15
16
  }
16
17
 
17
18
  def at_least_one_cluster_entity
@@ -20,8 +21,15 @@ module Klastera::Concerns::Clusterizable
20
21
  end
21
22
  end
22
23
 
24
+ ##
25
+ # This is a legacy method and we don't recommend using it.
26
+ # Implement directly Klastera.entity_clusters_string_list instead of this method.
27
+ # TODO: In order to deprecate it, you will need to perform some changes in the main app
28
+ ##
23
29
  def clusters_string_separated_by(separator,attribute=:name)
24
- self.cluster_entities.map{|ce|ce.cluster.send(attribute)}.join(separator)
30
+ Klastera.entity_clusters_string_list!(
31
+ self.cluster_entities, separator, attribute
32
+ )
25
33
  end
26
34
 
27
35
  def has_one_cluster_entity
@@ -29,6 +37,12 @@ module Klastera::Concerns::Clusterizable
29
37
  return errors.add(:cluster_entities, I18n.t('klastera.messages.has_one_cluster_entity'))
30
38
  end
31
39
  end
40
+
41
+ def uniqueness_of_cluster_entity_record
42
+ if cluster_entities.map(&:cluster_id).uniq.size != cluster_entities.size
43
+ return errors.add(:cluster_entities, I18n.t('klastera.messages.duplicated_cluster_entity') )
44
+ end
45
+ end
32
46
  end
33
47
 
34
48
  module ClassMethods
@@ -1,6 +1,6 @@
1
1
  <tr class="nested-fields">
2
2
  <td class="field">
3
- <%= f.select :cluster_id, cluster_clusters.map{|c|[c.name,c.id]}, { include_blank: true }, { class: 'form-control' } %>
3
+ <%= f.select :cluster_id, @cluster_clusters.map{|c|[c.name,c.id]}, { include_blank: true }, { class: 'form-control' } %>
4
4
  </td>
5
5
  <td class="action vertical-align-middle text-center" width="44">
6
6
  <%= link_to_remove_association f, class: 'btn btn-danger btn-xs text-danger' do %>
@@ -1,4 +1,5 @@
1
1
  <% if cluster_organization.is_in_cluster_mode? %>
2
+ <% @cluster_clusters = cluster_clusters %>
2
3
  <div class="col-xs-12">
3
4
  <% if hide_title||=false %>
4
5
  <div class="form-group file required <%=f.object.class.name.parameterize%>_cluster_entity<%=' has-error' if f.object.errors.has_key?(:cluster_entities)%>">
@@ -26,6 +27,7 @@
26
27
  <table id="cluster-entities" class="table table-striped">
27
28
  <tbody class="cluster-entity-rows">
28
29
  <%= f.fields_for :cluster_entities do |cluster_entity|%>
30
+ <% next unless @cluster_clusters.map(&:id).include?(cluster_entity.try(:object).try(:cluster_id)) %>
29
31
  <%= render 'layouts/klastera/cluster_entity_fields', f: cluster_entity %>
30
32
  <% end %>
31
33
  </body>
@@ -61,6 +61,7 @@ es:
61
61
  at_least_one_cluster_entity: Debe agregar al menos un cluster
62
62
  record_action_successfully: Registro %{a} exitosamente
63
63
  cant_delete_the_last_record_in_required_suborganization_mode: No se puede eliminar el único cluster de esta organización
64
+ duplicated_cluster_entity: Hay un cluster duplicado
64
65
  new_cluster_id:
65
66
  nil: Cluster no existe
66
67
  same: Cluster no puede ser el mismo
@@ -5,6 +5,12 @@ module Klastera
5
5
 
6
6
  extend ActiveSupport::Concern
7
7
 
8
+ KLSTR_HELPERS = %i[
9
+ cluster_user cluster_organization user_has_more_than_one_cluster
10
+ cluster_scope cluster_clusters cluster_scope_filtered clusters_from
11
+ user_clusters_string_list set_collection_before_group_by_entity
12
+ ]
13
+
8
14
  class << self
9
15
 
10
16
  def set_cluster_entities_attributes!(entity,array_cluster_ids)
@@ -30,13 +36,15 @@ module Klastera
30
36
  end
31
37
 
32
38
  #
33
- # I like to wrap methods
39
+ # In cases you don't have the active_record_collection object to filter, this method helps you
40
+ # calling cluster_scope! before and pass the collction to filter_clusterized_collection_with!,
41
+ # but at the end of the day, I just like to wrap methods.
34
42
  #
35
- def cluster_scope_filtered!(scope,cluster_id,user,organization,includes=[])
43
+ def cluster_scope_filtered!(scope,cluster_id,user,organization)
36
44
  self.filter_clusterized_collection_with!(
37
- organization,
38
45
  cluster_id,
39
- self.cluster_scope!(user,organization,scope,includes)
46
+ self.cluster_scope!(scope,user,organization),
47
+ organization
40
48
  )
41
49
  end
42
50
 
@@ -44,74 +52,88 @@ module Klastera
44
52
  # In order to this works, active_record_collection argument
45
53
  # should be passed through cluster_scope! method before.
46
54
  #
47
- def filter_clusterized_collection_with!(cluster_organization,cluster_id,active_record_collection)
55
+ def filter_clusterized_collection_with!(cluster_id,active_record_collection,cluster_organization)
48
56
  if cluster_organization.is_in_cluster_mode?
57
+
58
+ # IMPORTANT
59
+ # The next block was commented on because cluster_scope! method is not returning
60
+ # the cluster_entities within the scope anymore and it doesn't make any sense trying
61
+ # to filter based on force/use/show logic. Nevertheless, someday we will need it again.
62
+
63
+ # # If cluster_id is nil we will try to filter including unclustered entities active_record_collection wsas
64
+ # unless cluster_id.present?
65
+ # # Based on force/use/show definition we don't really need this validation. A force cluster organization won't return an entity that
66
+ # # doesn't belong to a cluster. Nevertheless we don't know if active_record_collection argument is fully definition-compliant.
67
+ # if cluster_organization.optional_suborganization_mode?
68
+ # cluster_array << nil
69
+ # end
70
+ # end
71
+
49
72
  if cluster_id.present?
50
- cluster_array = [cluster_id]
51
- # Based on force/use/show definition we don't really need this validation.
52
- # A force cluster organization won't return an entity out of a cluster, but
53
- # we don't know if the clusterized entities are fully definition-compliant.
54
- cluster_array << nil if cluster_organization.optional_suborganization_mode?
73
+ cluster_array = [cluster_id] unless cluster_id.is_a?(Array)
74
+ # The ActiveRecordCollection argument should have previously eager-loaded the cluster entities, thus the join statement is unnecessary.
55
75
  active_record_collection = active_record_collection.joins(:cluster_entities).where("cluster_entities.cluster_id": cluster_array)
56
76
  end
57
- # you may use a block only with clusterizable data
77
+
78
+ # You should use a block with clusterable data only
58
79
  yield(active_record_collection) if block_given?
59
80
  end
60
81
  active_record_collection
61
82
  end
62
83
 
63
- #
64
- #
65
- #
66
- def set_collection_before_group_by_entity!(cluster_organization,active_record_collection,model_class,entity_params)
84
+ ##
85
+ #
86
+ #
87
+ ##
88
+ def set_collection_before_group_by_entity!(active_record_collection,entity_params,cluster_organization)
67
89
  entity_params_keys = [:entity_name,:entity_attribute,:entity_id,:entity_id_attribute,:unamed]
90
+ entity_params[:entity_id] ||= nil #Ensures the entity_id attribute presence even if there is no filter
68
91
  entity_params = entity_params.slice(*entity_params_keys).values
69
- if model_class.try(:reflections).try(:keys).try(:include?,entity_params[0])
92
+ model_class = active_record_collection.model.base_class
93
+ model_relations = model_class.reflections.keys
94
+ if model_relations.include?(entity_params[0])
70
95
  entity_params << "#{entity_params[0]}_id".to_sym
71
96
  if entity_params[0] == 'cluster'
72
97
  entity_params << :unclustered if cluster_organization.is_in_cluster_mode?
73
98
  active_record_collection = Klastera.filter_clusterized_collection_with!(
74
- cluster_organization,
75
99
  entity_params[2],
76
- active_record_collection
100
+ active_record_collection,
101
+ cluster_organization
77
102
  )
78
103
  end
79
- yield(
80
- active_record_collection,
81
- entity_params_keys.zip(entity_params).to_h)
104
+ yield( active_record_collection, entity_params_keys.zip(entity_params).to_h )
82
105
  end
83
106
  end
84
107
 
85
108
  ##
86
109
  # Returns a ::Cluster::ActiveRecord_Relation from a given scope
87
110
  #
88
- def clusters_from!(user,organization,scope,includes=[])
89
- cluster_scope!(user,organization,scope,includes).related_clusters
111
+ def clusters_from!(scope,user,organization)
112
+ cluster_scope!(scope,user,organization).related_clusters
90
113
  end
91
114
 
92
115
  ##
93
116
  # Returns a scope filtered by clusters or its
94
117
  # organization if the cluster mode is not active.
95
118
  #
96
- def cluster_scope!(user,organization,scope,includes=[])
119
+ def cluster_scope!(scope,user,organization)
97
120
  scope_klass = scope_class(scope).where(organization_id: organization)
98
121
  session_clusters(user,organization) do |clusters|
99
122
  if organization.is_in_cluster_mode?
100
123
  scope_klass = scope_klass.select("DISTINCT ON (#{scope.table_name}.id) #{scope.table_name}.id, #{scope.table_name}.*")
101
- scope_klass = scope_klass.includes(includes) if includes.present?
102
124
  cluster_ids = clusters.map(&:id)
103
125
  if organization.required_suborganization_mode?
104
126
  scope_klass = scope_klass.joins(:cluster_entities).where( cluster_entities: { cluster_id: cluster_ids } )
105
127
  else
128
+ or_these_cluster_ids = cluster_ids.present? ? " OR cluster_entities.cluster_id IN (#{cluster_ids.join(",")})" : ""
106
129
  scope_klass = scope_klass.joins("
107
130
  LEFT OUTER JOIN cluster_entities
108
- ON cluster_entities.cluster_id IN (#{cluster_ids.join(",")})
109
- AND entity_id = #{scope.table_name}.id
131
+ ON entity_id = #{scope.table_name}.id
110
132
  AND entity_type = '#{scope}'
111
- ")
133
+ ").where("cluster_entities.id IS NULL#{or_these_cluster_ids}")
112
134
  end
113
135
  # Provisional fix to avoid SQL clashes due to DISTINCT ON clause
114
- scope_klass = scope_class(scope).where(organization_id: organization).where(id: scope_klass.map(&:id))
136
+ scope_klass = scope_class(scope).eager_load(:cluster_entities).where(id: scope_klass.map(&:id), organization_id: organization)
115
137
  end
116
138
  end
117
139
  scope_klass
@@ -143,38 +165,42 @@ module Klastera
143
165
  end
144
166
  clusters
145
167
  end
146
- end
147
168
 
148
- included do
149
- if respond_to?(:helper_method)
150
- helper_method :cluster_scope
151
- helper_method :user_cluster
152
- helper_method :cluster_user
153
- helper_method :cluster_organization
154
- helper_method :cluster_clusters
155
- helper_method :cluster_scope_filtered
156
- helper_method :user_has_more_than_one_cluster
157
- helper_method :clusters_from
169
+ ##
170
+ # Return a string with cluster attribute separated by separator argument
171
+ # A array of cluster ids can be passed fo filter the result
172
+ #
173
+ def entity_clusters_string_list!(cluster_entities,separator,attribute=:name,allowed_cluster_ids=nil)
174
+ _cluster_entities = cluster_entities.reject(&:nil?)
175
+ if allowed_cluster_ids.is_a?(Array)
176
+ _cluster_entities.select!{|ce| allowed_cluster_ids.include?(ce.cluster_id)}
177
+ end
178
+ _cluster_entities.map do |ce|
179
+ ce.cluster.try(attribute)
180
+ end.compact.join(separator)
158
181
  end
159
- if respond_to?(:hide_action)
160
- hide_action :cluster_scope
161
- hide_action :cluster_scope=
162
- hide_action :user_cluster
163
- hide_action :user_cluster=
164
- hide_action :cluster_user
165
- hide_action :cluster_user=
166
- hide_action :cluster_organization
167
- hide_action :cluster_organization=
168
- hide_action :cluster_clusters
169
- hide_action :cluster_clusters=
170
- hide_action :cluster_scope_filtered
171
- hide_action :cluster_scope_filtered=
172
- hide_action :user_has_more_than_one_cluster
173
- hide_action :user_has_more_than_one_cluster=
174
- hide_action :clusters_from
175
- hide_action :clusters_from=
182
+
183
+ ##
184
+ # cluster_clusters needs the logged user and its organization
185
+ # that why, we perfomed this logic here
186
+ #
187
+ def user_clusters_string_list!(user,organization,cluster_entities,separator,attribute=:name)
188
+ @_session_clusters ||= self.session_clusters(user,organization)
189
+ self.entity_clusters_string_list!(cluster_entities, separator, attribute, @_session_clusters.map(&:id))
176
190
  end
177
- before_action :set_the_lonely_cluster, only: %i[ create update ]
191
+ end
192
+
193
+ def cluster_user
194
+ current_user
195
+ end
196
+
197
+ def cluster_organization
198
+ current_organization
199
+ end
200
+
201
+ def user_has_more_than_one_cluster
202
+ @cluster_clusters ||= cluster_clusters
203
+ @cluster_clusters.size > 1
178
204
  end
179
205
 
180
206
  def set_the_lonely_cluster
@@ -186,52 +212,69 @@ module Klastera
186
212
  end
187
213
  end
188
214
 
189
- def cluster_scope(scope,includes=[])
190
- Klastera.cluster_scope!(cluster_user,cluster_organization,scope,includes)
215
+ def set_cluster_filter
216
+ @filter = ::ClusterFilter.new(cluster_filter_params)
217
+ end
218
+
219
+ def cluster_filter_params
220
+ parameters = params.require(:cluster_filter) rescue nil
221
+ return {} if parameters.blank?
222
+ parameters.permit(*cluster_filter_permit_params)
191
223
  end
192
224
 
193
- def cluster_user
194
- current_user
225
+ def cluster_filter_permit_params
226
+ [ :cluster_id ].concat( ::ClusterFilter.attributes )
195
227
  end
196
228
 
197
- def cluster_organization
198
- current_organization
229
+ def filter_clusterized_collection_with(cluster_id,active_record_collection)
230
+ Klastera.filter_clusterized_collection_with!(cluster_id,active_record_collection,cluster_organization)
231
+ end
232
+
233
+ def cluster_scope(scope)
234
+ Klastera.cluster_scope!(scope,cluster_user,cluster_organization)
199
235
  end
200
236
 
201
237
  def cluster_clusters
202
238
  Klastera.session_clusters(cluster_user,cluster_organization)
203
239
  end
204
240
 
205
- def cluster_scope_filtered(scope,cluster_id,includes=[])
241
+ def cluster_scope_filtered(scope,cluster_id)
206
242
  Klastera.cluster_scope_filtered!(
207
243
  scope,
208
244
  cluster_id,
209
245
  cluster_user,
210
- cluster_organization,
211
- includes
246
+ cluster_organization
212
247
  )
213
248
  end
214
249
 
215
- def user_has_more_than_one_cluster
216
- @cluster_clusters ||= cluster_clusters
217
- @cluster_clusters.size > 1
218
- end
219
-
220
- def clusters_from(scope,includes=[])
221
- Klastera.clusters_from!(cluster_user,cluster_organization,scope,includes)
250
+ def clusters_from(scope)
251
+ Klastera.clusters_from!(scope,cluster_user,cluster_organization)
222
252
  end
223
253
 
224
- def set_cluster_filter
225
- @filter = ::ClusterFilter.new(cluster_filter_params)
254
+ def user_clusters_string_list(object_entity,separator,attribute=:name)
255
+ Klastera.user_clusters_string_list!(
256
+ cluster_user,
257
+ cluster_organization,
258
+ object_entity.try(:cluster_entities),
259
+ separator,
260
+ attribute
261
+ )
226
262
  end
227
263
 
228
- def cluster_filter_params
229
- parameters = params.require(:cluster_filter) rescue nil
230
- return {} if parameters.blank?
231
- parameters.permit(*cluster_filter_permit_params)
264
+ def set_collection_before_group_by_entity(active_record_collection,entity_params,&block)
265
+ Klastera.set_collection_before_group_by_entity!(active_record_collection,params,cluster_organization,&block)
232
266
  end
233
267
 
234
- def cluster_filter_permit_params
235
- [ :cluster_id ].concat( ::ClusterFilter.attributes )
268
+ included do
269
+ Klastera::KLSTR_HELPERS.each do |action|
270
+ if respond_to?(:helper_method)
271
+ helper_method(action)
272
+ end
273
+ if respond_to?(:hide_action)
274
+ hide_action(helper)
275
+ hide_action("#{helper}=")
276
+ end
277
+ end
278
+ before_action :set_the_lonely_cluster, only: %i[ create update ]
236
279
  end
237
280
  end
@@ -1,3 +1,3 @@
1
1
  module Klastera
2
- VERSION = "1.2.2"
3
- end
2
+ VERSION = "1.2.4.2"
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.2.2
4
+ version: 1.2.4.2
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-06-05 00:00:00.000000000 Z
11
+ date: 2020-06-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -54,7 +54,6 @@ files:
54
54
  - app/controllers/klastera/application_controller.rb
55
55
  - app/controllers/klastera/clusters_controller.rb
56
56
  - app/helpers/klastera/application_helper.rb
57
- - app/helpers/klastera/clusters_helper.rb
58
57
  - app/models/klastera/cluster.rb
59
58
  - app/models/klastera/cluster_entity.rb
60
59
  - app/models/klastera/cluster_filter.rb
@@ -1,4 +0,0 @@
1
- module Klastera
2
- module ClustersHelper
3
- end
4
- end