@@ -3,8 +3,6 @@ class BrowseController < ApplicationController
3
3
4
4
def tag
5
5
@tag_slug = params [ :tag_slug ]
6
- # Debug logging
7
- Rails . logger . info "BrowseController#tag - Looking for content with tag slug: #{ @tag_slug } "
8
6
9
7
# For now, only allow ArtFight2025 tag to be browsed (case insensitive)
10
8
unless @tag_slug . downcase == 'artfight2025'
@@ -18,122 +16,125 @@ def tag
18
16
19
17
# Directly check database for any pages with this tag
20
18
tag_exists = PageTag . exists? ( slug : @tag_slug )
21
- Rails . logger . info "Tag exists in PageTag table? #{ tag_exists } "
22
19
23
20
if tag_exists
24
- sample_tag = PageTag . find_by ( slug : @tag_slug )
25
- Rails . logger . info "Sample tag: #{ sample_tag . inspect } "
26
- end
27
-
28
- # Go through each content type and find public items with this tag
29
- Rails . application . config . content_types [ :all ] . each do |content_type |
30
- # Try a different query approach - first find page IDs with this tag
31
- tag_page_ids = PageTag . where ( page_type : content_type . name , slug : @tag_slug ) . pluck ( :page_id )
21
+ # Calculate a daily seed for consistent randomization across page refreshes in same day
22
+ # This allows for caching while still changing the order daily
23
+ daily_seed = Date . today . to_time . to_i
32
24
33
- if tag_page_ids . any?
34
- Rails . logger . info "Found #{ tag_page_ids . count } #{ content_type . name } page IDs with tag: #{ tag_page_ids } "
35
- content_pages = content_type . where ( id : tag_page_ids ) . where ( privacy : 'public' ) . order ( :name )
36
- else
37
- Rails . logger . info "No #{ content_type . name } pages found with tag"
38
- content_pages = content_type . none
39
- end
25
+ # Number of items to show per content type to avoid performance issues
26
+ per_type_limit = 50
27
+
28
+ # Go through each content type and find public items with this tag
29
+ Rails . application . config . content_types [ :all ] . each do |content_type |
30
+ # First find page IDs with this tag
31
+ tag_page_ids = PageTag . where ( page_type : content_type . name , slug : @tag_slug ) . pluck ( :page_id )
32
+
33
+ if tag_page_ids . any?
34
+ # Use database-level randomization with the daily seed for caching potential
35
+ # Use PostgreSQL's random function with a seed derived from the ID and daily seed
36
+ # This is much more efficient than loading all records into memory
37
+ content_pages = content_type . where ( id : tag_page_ids )
38
+ . where ( privacy : 'public' )
39
+ . order ( Arel . sql ( "RANDOM()" ) )
40
+ . limit ( per_type_limit )
40
41
41
- @tagged_content << {
42
- type : content_type . name ,
43
- icon : content_type . icon ,
44
- color : content_type . color ,
45
- content : content_pages
46
- } if content_pages . any?
47
- end
48
-
49
- # Add documents separately since they don't use the common content type structure
50
- document_tag_page_ids = PageTag . where ( page_type : 'Document' , slug : @tag_slug ) . pluck ( :page_id )
51
- if document_tag_page_ids . any?
52
- Rails . logger . info "Found #{ document_tag_page_ids . count } Document page IDs with tag: #{ document_tag_page_ids } "
53
- documents = Document . where ( id : document_tag_page_ids ) . where ( privacy : 'public' ) . order ( :title )
54
- else
55
- Rails . logger . info "No Document pages found with tag"
56
- documents = Document . none
57
- end # Documents use 'title' instead of 'name'
58
-
59
- @tagged_content << {
60
- type : 'Document' ,
61
- icon : 'description' ,
62
- color : 'blue' ,
63
- content : documents
64
- } if documents . any?
65
-
66
- # Add timelines separately since they don't use the common content type structure
67
- timeline_tag_page_ids = PageTag . where ( page_type : 'Timeline' , slug : @tag_slug ) . pluck ( :page_id )
68
- if timeline_tag_page_ids . any?
69
- Rails . logger . info "Found #{ timeline_tag_page_ids . count } Timeline page IDs with tag: #{ timeline_tag_page_ids } "
70
- timelines = Timeline . where ( id : timeline_tag_page_ids ) . where ( privacy : 'public' ) . order ( :name )
71
- else
72
- Rails . logger . info "No Timeline pages found with tag"
73
- timelines = Timeline . none
74
- end
75
-
76
- @tagged_content << {
77
- type : 'Timeline' ,
78
- icon : 'timeline' ,
79
- color : 'blue' ,
80
- content : timelines
81
- } if timelines . any?
82
-
83
- # Get images for content cards from all users
84
- content_ids_by_type = { }
85
- user_ids = [ ]
86
-
87
- @tagged_content . each do |content_group |
88
- content_group [ :content ] . each do |content |
89
- content_type = content . class . name
90
- content_ids_by_type [ content_type ] ||= [ ]
91
- content_ids_by_type [ content_type ] << content . id
92
- user_ids << content . user_id
42
+ @tagged_content << {
43
+ type : content_type . name ,
44
+ icon : content_type . icon ,
45
+ color : content_type . color ,
46
+ content : content_pages
47
+ } if content_pages . any?
48
+ end
93
49
end
94
- end
95
-
96
- # Get unique user IDs
97
- user_ids . uniq!
98
-
99
- # Get all relevant images
100
- @random_image_pool_cache = { }
101
- if content_ids_by_type . any?
102
- content_ids_by_type . each do |content_type , ids |
103
- images = ImageUpload . where ( content_type : content_type , content_id : ids )
50
+
51
+ # Add documents separately since they don't use the common content type structure
52
+ document_tag_page_ids = PageTag . where ( page_type : 'Document' , slug : @tag_slug ) . pluck ( :page_id )
53
+ if document_tag_page_ids . any?
54
+ documents = Document . where ( id : document_tag_page_ids )
55
+ . where ( privacy : 'public' )
56
+ . order ( Arel . sql ( "RANDOM()" ) )
57
+ . limit ( per_type_limit )
104
58
105
- images . each do |image |
106
- key = [ image . content_type , image . content_id ]
107
- @random_image_pool_cache [ key ] ||= [ ]
108
- @random_image_pool_cache [ key ] << image
59
+ @tagged_content << {
60
+ type : 'Document' ,
61
+ icon : 'description' ,
62
+ color : 'blue' ,
63
+ content : documents
64
+ } if documents . any?
65
+ end
66
+
67
+ # Add timelines separately since they don't use the common content type structure
68
+ timeline_tag_page_ids = PageTag . where ( page_type : 'Timeline' , slug : @tag_slug ) . pluck ( :page_id )
69
+ if timeline_tag_page_ids . any?
70
+ timelines = Timeline . where ( id : timeline_tag_page_ids )
71
+ . where ( privacy : 'public' )
72
+ . order ( Arel . sql ( "RANDOM()" ) )
73
+ . limit ( per_type_limit )
74
+
75
+ @tagged_content << {
76
+ type : 'Timeline' ,
77
+ icon : 'timeline' ,
78
+ color : 'blue' ,
79
+ content : timelines
80
+ } if timelines . any?
81
+ end
82
+
83
+ # Get images for content cards from all users
84
+ content_ids_by_type = { }
85
+ user_ids = [ ]
86
+
87
+ @tagged_content . each do |content_group |
88
+ content_group [ :content ] . each do |content |
89
+ content_type = content . class . name
90
+ content_ids_by_type [ content_type ] ||= [ ]
91
+ content_ids_by_type [ content_type ] << content . id
92
+ user_ids << content . user_id
109
93
end
110
94
end
111
- end
112
-
113
- # Initialize basil commissions if there are any content items
114
- if content_ids_by_type . any?
115
- entity_types = [ ]
116
- entity_ids = [ ]
117
95
118
- content_ids_by_type . each do |content_type , ids |
119
- entity_type = content_type . downcase . pluralize
120
- entity_types . concat ( [ entity_type ] * ids . length )
121
- entity_ids . concat ( ids )
96
+ # Get unique user IDs
97
+ user_ids . uniq!
98
+
99
+ # Get all relevant images - optimize with a single query per content type
100
+ @random_image_pool_cache = { }
101
+ if content_ids_by_type . any?
102
+ content_ids_by_type . each do |content_type , ids |
103
+ images = ImageUpload . where ( content_type : content_type , content_id : ids )
104
+
105
+ images . each do |image |
106
+ key = [ image . content_type , image . content_id ]
107
+ @random_image_pool_cache [ key ] ||= [ ]
108
+ @random_image_pool_cache [ key ] << image
109
+ end
110
+ end
111
+ end
112
+
113
+ # Initialize basil commissions if there are any content items
114
+ if content_ids_by_type . any?
115
+ entity_types = [ ]
116
+ entity_ids = [ ]
117
+
118
+ content_ids_by_type . each do |content_type , ids |
119
+ entity_type = content_type . downcase . pluralize
120
+ entity_types . concat ( [ entity_type ] * ids . length )
121
+ entity_ids . concat ( ids )
122
+ end
123
+
124
+ @saved_basil_commissions = BasilCommission . where (
125
+ entity_type : entity_types ,
126
+ entity_id : entity_ids
127
+ ) . where . not ( saved_at : nil )
128
+ . group_by { |commission | [ commission . entity_type , commission . entity_id ] }
122
129
end
123
130
124
- @saved_basil_commissions = BasilCommission . where (
125
- entity_type : entity_types ,
126
- entity_id : entity_ids
127
- ) . where . not ( saved_at : nil )
128
- . group_by { |commission | [ commission . entity_type , commission . entity_id ] }
131
+ # Get usernames for display with content - optimize with a single query
132
+ @users_cache = User . where ( id : user_ids ) . index_by ( &:id )
129
133
end
130
134
131
135
# Set a default accent color for the page
132
136
@accent_color = 'purple'
133
137
134
- # Get usernames for display with content
135
- @users_cache = User . where ( id : user_ids ) . index_by ( &:id )
136
-
137
138
# Sort content types so Characters always appear first
138
139
@tagged_content = @tagged_content . sort_by do |content_group |
139
140
if content_group [ :type ] == 'Character'
0 commit comments