@@ -3,8 +3,6 @@ class BrowseController < ApplicationController
33
44 def tag
55 @tag_slug = params [ :tag_slug ]
6- # Debug logging
7- Rails . logger . info "BrowseController#tag - Looking for content with tag slug: #{ @tag_slug } "
86
97 # For now, only allow ArtFight2025 tag to be browsed (case insensitive)
108 unless @tag_slug . downcase == 'artfight2025'
@@ -18,122 +16,125 @@ def tag
1816
1917 # Directly check database for any pages with this tag
2018 tag_exists = PageTag . exists? ( slug : @tag_slug )
21- Rails . logger . info "Tag exists in PageTag table? #{ tag_exists } "
2219
2320 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
3224
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 )
4041
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
9349 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 )
10458
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
10993 end
11094 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 = [ ]
11795
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 ] }
122129 end
123130
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 )
129133 end
130134
131135 # Set a default accent color for the page
132136 @accent_color = 'purple'
133137
134- # Get usernames for display with content
135- @users_cache = User . where ( id : user_ids ) . index_by ( &:id )
136-
137138 # Sort content types so Characters always appear first
138139 @tagged_content = @tagged_content . sort_by do |content_group |
139140 if content_group [ :type ] == 'Character'
0 commit comments