redmineup 1.1.14 → 1.1.15

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: edd9e2b69c72c5f3ec376bd59f68cd701bcb28a1ac81c7fbf31085acdd422e18
4
- data.tar.gz: 52bf3b2fd440ace540ba8d1eba5d297243ded63da5e806a9496d41c796f9d628
3
+ metadata.gz: 497432257e3dd60a1140adb02b491af3e36a669a8c2af4cb42fb810f09b26b4c
4
+ data.tar.gz: e07c21fc5a9358e9706fb2d922919c994a17013704d583cfd87282162a03c40e
5
5
  SHA512:
6
- metadata.gz: 1d196b8b574b8643412d71618072da558649c48748b92b471e7594743ebe6c7c2f03f8c3c523e5774034040bb4a802d77fe00713acfeb50b978bb1a46f605cee
7
- data.tar.gz: '07478c4976432e4103a50630d60fa691d153434a238e3811bae0d393ad4c1e24a5e17246268e569a1a03b023bd8b704ec15c55536dbb045ffd83db1cb1f12c56'
6
+ metadata.gz: '09ea94ec0283833d3c2daa10ca34239374eb64dccbfd8130dabea3f292947c0d9f88e92e33b5e17c544bacf0014f782aa712fbc280a5b7e45e5368d1f07ebb17'
7
+ data.tar.gz: 959335aba0d22370913ced0db6b826a93eb2a856422aa0e22a3f85d21a2c6d0cba6a5788068391441944db221ac300a555b7339dca588ee40a6348011bc58ab4
data/doc/CHANGELOG CHANGED
@@ -4,6 +4,10 @@ Redmine UP gem - general functions for plugins (tags, vote, viewing, currency)
4
4
  Copyright (C) 2011-2026 Kirill Bezrukov (RedmineUP)
5
5
  https://www.redmineup.com/
6
6
 
7
+ == 2026-10-11 v1.1.15
8
+
9
+ * Speeded up the tags list query (available_tags) on pages with a lot of tagged records
10
+
7
11
  == 2026-10-09 v1.1.14
8
12
 
9
13
  * Fixed missing calendar icons and extra padding in Redmine 6/7
@@ -129,43 +129,43 @@ module Redmineup
129
129
  #Return all avalible tags for a project or global
130
130
  #Example: Question.available_tags(:project => @project_id )
131
131
  def available_tags(options = {})
132
- projects = [[options[:project]], options[:projects]].flatten.compact
133
132
  limit = options[:limit].to_i.zero? ? 30 : options[:limit].to_i
134
- scope = Tag.where({})
135
- class_name = quote_string_value(base_class.name)
136
- join = []
137
- join << "JOIN #{Tagging.table_name} ON #{Tagging.table_name}.tag_id = #{Tag.table_name}.id "
138
- join << "JOIN #{table_name} ON #{table_name}.id = #{Tagging.table_name}.taggable_id
139
- AND #{Tagging.table_name}.taggable_type = #{class_name} "
140
- if attribute_names.include?('project_id') && projects.any?
141
- join << "JOIN #{Project.table_name} ON #{Project.table_name}.id = #{table_name}.project_id"
142
- scope = scope.where("#{table_name}.project_id IN (%s)", projects.map(&:id).join(','))
143
- end
133
+ counts_sql = Tag.connection.unprepared_statement { tagged_records_scope(options).to_sql }
144
134
 
135
+ scope = Tag.joins("JOIN (#{counts_sql}) tag_counts ON tag_counts.tag_id = #{Tag.table_name}.id")
136
+ scope = scope.select("#{Tag.table_name}.*, tag_counts.count AS count")
145
137
  if options[:name_like].present?
146
138
  scope = scope.where("LOWER(#{Tag.table_name}.name) LIKE LOWER(?)", "%#{options[:name_like]}%")
147
139
  end
140
+ scope.order("#{Tag.table_name}.name").limit(limit)
141
+ end
148
142
 
149
- group_fields = ''
150
- group_fields << ", #{Tag.table_name}.created_at" if Tag.respond_to?(:created_at)
151
- group_fields << ", #{Tag.table_name}.updated_at" if Tag.respond_to?(:updated_at)
152
- group_fields << ", #{Tag.table_name}.color" if Tag.column_names.include?('color')
143
+ # tag_id => number of visible taggables. Extension point for available_tags.
144
+ def tagged_records_scope(options = {})
145
+ projects = [[options[:project]], options[:projects]].flatten.compact
146
+ scope = Tagging.unscoped.
147
+ joins("JOIN #{table_name} ON #{table_name}.id = #{Tagging.table_name}.taggable_id").
148
+ where("#{Tagging.table_name}.taggable_type = ?", base_class.name).
149
+ group("#{Tagging.table_name}.tag_id").
150
+ select("#{Tagging.table_name}.tag_id, COUNT(DISTINCT #{Tagging.table_name}.taggable_id) AS count")
151
+
152
+ projects_joined = false
153
+ if attribute_names.include?('project_id') && projects.any?
154
+ scope = scope.joins("JOIN #{Project.table_name} ON #{Project.table_name}.id = #{table_name}.project_id").
155
+ where("#{table_name}.project_id IN (?)", projects.map(&:id))
156
+ projects_joined = true
157
+ end
153
158
 
154
159
  if base_class.respond_to?(:visible_condition)
155
160
  visible_condition = base_class.visible_condition(User.current)
156
- if visible_condition.include?('project_id') && join.all? { |jn| jn.exclude?('JOIN projects') }
157
- join << "JOIN #{Project.table_name} ON #{Project.table_name}.id = #{table_name}.project_id"
161
+ if visible_condition.include?('project_id') && !projects_joined
162
+ scope = scope.joins("JOIN #{Project.table_name} ON #{Project.table_name}.id = #{table_name}.project_id")
158
163
  end
159
164
  scope = scope.where(visible_condition)
160
165
  end
161
- scope = scope.joins(join.join(' '))
162
- scope = scope.select("#{Tag.table_name}.*, COUNT(DISTINCT #{Tagging.table_name}.taggable_id) AS count")
163
- scope = scope.group("#{Tag.table_name}.id, #{Tag.table_name}.name #{group_fields}")
164
- scope = scope.having('COUNT(*) > 0')
165
- scope = scope.order("#{Tag.table_name}.name")
166
- scope = scope.limit(limit)
167
166
  scope
168
167
  end
168
+
169
169
  # Returns an array of related tags.
170
170
  # Related tags are all the other tags that are found on the models tagged with the provided tags.
171
171
  #
@@ -1,3 +1,3 @@
1
1
  module Redmineup
2
- VERSION = '1.1.14'
2
+ VERSION = '1.1.15'
3
3
  end
data/redmineup.gemspec CHANGED
@@ -13,7 +13,7 @@ Gem::Specification.new do |spec|
13
13
  spec.homepage = "https://www.redmineup.com"
14
14
  spec.license = "GPL-2.0"
15
15
 
16
- spec.files = `git ls-files -z`.split("\x0")
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.start_with?("doc/dev/") || %w[AGENTS.md GLOSSARY.md].include?(f) }
17
17
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redmineup
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.14
4
+ version: 1.1.15
5
5
  platform: ruby
6
6
  authors:
7
7
  - RedmineUP
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-10-09 00:00:00.000000000 Z
11
+ date: 2026-10-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails