Skip to content

UX: show complete URL path if website domain is same as instance domain#6

Open
ShashankFC wants to merge 1 commit into
url-handling-prefrom
url-handling-post
Open

UX: show complete URL path if website domain is same as instance domain#6
ShashankFC wants to merge 1 commit into
url-handling-prefrom
url-handling-post

Conversation

@ShashankFC

@ShashankFC ShashankFC commented Jan 5, 2026

Copy link
Copy Markdown
Collaborator

Test 6

Summary by CodeRabbit

  • Refactor

    • Reorganized code architecture to improve maintainability and better separate concerns.
  • Tests

    • Enhanced test coverage for website domain name handling with new test cases covering different domain matching scenarios, including host name derivation and path normalization based on domain configuration relationships.

✏️ Tip: You can customize this high-level summary in your review settings.


Replicated from ai-code-review-evaluation/discourse-coderabbit#6

@ShashankFC

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jan 13, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Jan 13, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

The changes migrate the websiteName computed property from the user controller to the serializer as website_name. The template is updated to reference the new model attribute. Tests verify the new serializer logic that derives the website name based on hostname matching.

Changes

Cohort / File(s) Summary
Controller Updates
app/assets/javascripts/discourse/controllers/user.js.es6
Removed websiteName computed property that previously derived a value by splitting the website URL.
Model & Serializer Updates
app/assets/javascripts/discourse/models/user.js.es6,
app/serializers/user_serializer.rb
Updated JSDoc comment reference. Added new website_name computed attribute to serializer with logic to normalize site names based on hostname matching (returns host name or complete path depending on domain configuration).
Template Updates
app/assets/javascripts/discourse/templates/user/user.hbs
Replaced references to websiteName with model.website_name in conditional checks and display text while preserving website link behavior.
Test Coverage
spec/serializers/user_serializer_spec.rb
Updated test data and expectations for website URL. Added three new test cases covering website_name behavior: different domains, matching domains, and parent domain scenarios.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A website name hops from controller to serializer's nest,
Template now points to model, putting REST to the test.
Domain logic blooms wherever the hostname does match,
Tests scurry through paths—no edge case left to catch! 🌾

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main refactoring: moving website_name logic from controller to serializer and updating template references to use model.website_name for proper domain handling.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In @app/serializers/user_serializer.rb:
- Around line 153-155: Rename the conditional serializer method
include_website_name to include_website_name? so ActiveModelSerializers
recognizes it as a conditional include; keep the implementation returning
website.present? (i.e., have include_website_name? return website.present?) and
update any references to the old method name if present.
🧹 Nitpick comments (2)
app/serializers/user_serializer.rb (1)

137-151: Consider simplifying this method to reduce complexity and avoid repeated URI parsing.

The method parses URI(website.to_s) up to 4 times and uses a rescue modifier that silently swallows all exceptions. This also addresses the static analysis warnings about high cyclomatic complexity.

♻️ Proposed refactor
   def website_name
-    website_host = URI(website.to_s).host rescue nil
-    discourse_host = Discourse.current_hostname
-    return if website_host.nil?
-    if website_host == discourse_host
-      # example.com == example.com
-      website_host + URI(website.to_s).path
-    elsif (website_host.split('.').length == discourse_host.split('.').length) && discourse_host.split('.').length > 2
-      # www.example.com == forum.example.com
-      website_host.split('.')[1..-1].join('.') == discourse_host.split('.')[1..-1].join('.') ? website_host + URI(website.to_s).path : website_host
-    else
-      # example.com == forum.example.com
-      discourse_host.ends_with?("." << website_host) ? website_host + URI(website.to_s).path : website_host
-    end
+    uri = URI(website.to_s)
+    website_host = uri.host
+    return if website_host.nil?
+
+    discourse_host = Discourse.current_hostname
+    website_path = uri.path
+
+    if same_domain?(website_host, discourse_host)
+      website_host + website_path
+    else
+      website_host
+    end
+  rescue URI::InvalidURIError
+    nil
   end
+
+  private
+
+  def same_domain?(website_host, discourse_host)
+    return true if website_host == discourse_host
+
+    website_parts = website_host.split('.')
+    discourse_parts = discourse_host.split('.')
+
+    # Check if same parent domain with different subdomains (e.g., www.example.com vs forum.example.com)
+    if website_parts.length == discourse_parts.length && discourse_parts.length > 2
+      return website_parts[1..-1] == discourse_parts[1..-1]
+    end
+
+    # Check if website is parent domain of discourse host (e.g., example.com vs forums.example.com)
+    discourse_host.end_with?(".#{website_host}")
+  end
spec/serializers/user_serializer_spec.rb (1)

76-91: Consider adding a test for sibling subdomains.

The serializer has specific logic for handling sibling subdomains (e.g., www.example.com vs forum.example.com at lines 144-146 in user_serializer.rb), but this case isn't covered by the tests.

📝 Additional test case
it "returns complete website path when website and instance are sibling subdomains" do
  user.user_profile.website = 'http://www.example.com/user'
  Discourse.stubs(:current_hostname).returns('forum.example.com')
  serialized = UserSerializer.new(user, scope: Guardian.new, root: false).as_json
  expect(serialized[:website_name]).to eq 'www.example.com/user'
end
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7a5fbae and 267d8be.

📒 Files selected for processing (5)
  • app/assets/javascripts/discourse/controllers/user.js.es6
  • app/assets/javascripts/discourse/models/user.js.es6
  • app/assets/javascripts/discourse/templates/user/user.hbs
  • app/serializers/user_serializer.rb
  • spec/serializers/user_serializer_spec.rb
💤 Files with no reviewable changes (1)
  • app/assets/javascripts/discourse/controllers/user.js.es6
🧰 Additional context used
🧬 Code graph analysis (2)
spec/serializers/user_serializer_spec.rb (1)
app/serializers/user_serializer.rb (1)
  • website (133-135)
app/serializers/user_serializer.rb (2)
lib/discourse.rb (1)
  • current_hostname (178-184)
lib/global_path.rb (1)
  • path (2-4)
🪛 RuboCop (1.82.1)
app/serializers/user_serializer.rb

[convention] 137-151: Assignment Branch Condition size for website_name is too high. [<2, 35, 12> 37.05/23]

(Metrics/AbcSize)


[convention] 137-151: Cyclomatic complexity for website_name is too high. [8/7]

(Metrics/CyclomaticComplexity)


[convention] 137-151: Perceived complexity for website_name is too high. [9/8]

(Metrics/PerceivedComplexity)


[convention] 138-138: Avoid using rescue in its modifier form.

(Style/RescueModifier)

🔇 Additional comments (2)
app/assets/javascripts/discourse/models/user.js.es6 (1)

56-66: LGTM!

The JSDoc correction properly aligns the @property tag with the actual profileBackground property it documents.

app/assets/javascripts/discourse/templates/user/user.hbs (1)

66-73: LGTM!

The template correctly references the new model.website_name attribute from the serializer while preserving model.website for the full URL in the href. The conditional logic and display behavior are maintained.

Comment on lines +153 to +155
def include_website_name
website.present?
end

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Missing ? suffix on include method.

ActiveModelSerializers expects the method to be named include_website_name? with a trailing ? for the conditional inclusion to work. Without this, the attribute will always be serialized regardless of whether website is present.

🐛 Proposed fix
-  def include_website_name
+  def include_website_name?
     website.present?
   end
🤖 Prompt for AI Agents
In @app/serializers/user_serializer.rb around lines 153 - 155, Rename the
conditional serializer method include_website_name to include_website_name? so
ActiveModelSerializers recognizes it as a conditional include; keep the
implementation returning website.present? (i.e., have include_website_name?
return website.present?) and update any references to the old method name if
present.

Comment on lines +76 to 91
context "has a website name" do
it "returns website host name when instance domain is not same as website domain" do
Discourse.stubs(:current_hostname).returns('discourse.org')
expect(json[:website_name]).to eq 'example.com'
end

it "returns complete website path when instance domain is same as website domain" do
Discourse.stubs(:current_hostname).returns('example.com')
expect(json[:website_name]).to eq 'example.com/user'
end

it "returns complete website path when website domain is parent of instance domain" do
Discourse.stubs(:current_hostname).returns('forums.example.com')
expect(json[:website_name]).to eq 'example.com/user'
end
end

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Tests may not work as expected due to let memoization order.

The json variable is memoized via let at line 21, which calls serializer.as_json. The stubs for Discourse.current_hostname are set up after json would be evaluated on first access. Depending on when json is first accessed, the stub might not be in effect.

Consider using let! to force eager evaluation after stubbing, or restructure to ensure stubs are in place before serialization:

🐛 Proposed fix
       context "has a website name" do
         it "returns website host name when instance domain is not same as website domain" do
           Discourse.stubs(:current_hostname).returns('discourse.org')
-          expect(json[:website_name]).to eq 'example.com'
+          serialized = UserSerializer.new(user, scope: Guardian.new, root: false).as_json
+          expect(serialized[:website_name]).to eq 'example.com'
         end

         it "returns complete website path when instance domain is same as website domain" do
           Discourse.stubs(:current_hostname).returns('example.com')
-          expect(json[:website_name]).to eq 'example.com/user'
+          serialized = UserSerializer.new(user, scope: Guardian.new, root: false).as_json
+          expect(serialized[:website_name]).to eq 'example.com/user'
         end

         it "returns complete website path when website domain is parent of instance domain" do
           Discourse.stubs(:current_hostname).returns('forums.example.com')
-          expect(json[:website_name]).to eq 'example.com/user'
+          serialized = UserSerializer.new(user, scope: Guardian.new, root: false).as_json
+          expect(serialized[:website_name]).to eq 'example.com/user'
         end
       end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants