การกำหนดเส้นทาง Rails เพื่อจัดการกับหลายโดเมนในแอปพลิเคชันเดียว


90

ฉันไม่สามารถหาวิธีแก้ปัญหานี้ได้แม้จะมีคำถามที่คล้ายกันหลายข้อที่นี่และที่อื่น ๆ ดูเหมือนว่าคำถามนี้ยังไม่ได้รับคำตอบสำหรับ Rails 3 ดังนั้นต่อไปนี้:

ฉันมีแอปพลิเคชันที่อนุญาตให้ผู้ใช้สร้างโดเมนย่อยของตนเองซึ่งมีอินสแตนซ์ของแอปพลิเคชันอยู่ ในขณะที่ทางรถไฟ 2 คุณได้ทำหน้าที่ดีที่สุดโดยใช้อัญมณีโดเมนย่อย-Fu, ในรุ่นที่ 3 มันเป็นอย่างมากที่เรียบง่ายตาม Railscast - http://railscasts.com/episodes/221-subdomains-in-rails-3

นั่นเป็นสิ่งที่ดี แต่ฉันก็ต้องการให้ตัวเลือกสำหรับผู้ใช้ในการเชื่อมโยงชื่อโดเมนของตนเองกับบัญชีของพวกเขา ดังนั้นแม้ว่าพวกเขาอาจมีhttp://userx.mydomain.comแต่ฉันก็อยากให้พวกเขาเลือกที่จะเชื่อมโยงhttp://userx.comด้วย

ฉันพบข้อมูลอ้างอิงบางประการเกี่ยวกับการทำสิ่งนี้ใน Rails 2 แต่เทคนิคเหล่านั้นดูเหมือนจะไม่ได้ผลอีกต่อไป (โดยเฉพาะอย่างยิ่งอันนี้: https://feefighters.com/blog/hosting-multiple-domains-from-a-single-rails -app / )

ใครสามารถแนะนำวิธีใช้เส้นทางเพื่อยอมรับโดเมนที่กำหนดเองและส่งต่อไปยังคอนโทรลเลอร์เพื่อให้ฉันสามารถแสดงเนื้อหาที่เหมาะสมได้

อัปเดต : ตอนนี้ฉันได้รับคำตอบเกือบทั้งหมดแล้วขอบคุณการตอบสนองที่ทันท่วงทีของ Leonid และรูปลักษณ์ใหม่ของโค้ด ในที่สุดมันต้องการการเพิ่มเติมจากรหัสโดเมนย่อยที่มีอยู่ซึ่งฉันใช้อยู่ (จากโซลูชัน Railscast) จากนั้นจึงเพิ่มบิตให้กับ route.rb ฉันยังไปไม่ถึงที่นั่น แต่ฉันต้องการโพสต์สิ่งที่ฉันมีจนถึงตอนนี้

ใน lib / subdomain.rb:

class Subdomain
  def self.matches?(request)
    request.subdomain.present? && request.subdomain != "www"
  end
end

class Domain
  def self.matches?(request)
    request.domain.present? && request.domain != "mydomain.com"
  end
end

ฉันได้เพิ่มคลาสที่สองโดยเลียนแบบคลาสแรกซึ่งเป็นที่ทราบกันดีว่าใช้งานได้ ฉันเพียงแค่เพิ่มเงื่อนไขที่ทำให้มั่นใจได้ว่าโดเมนขาเข้าไม่ใช่โดเมนที่ฉันโฮสต์ไซต์หลัก

คลาสนี้ใช้ใน route.rb:

require 'subdomain'
constraints(Domain) do
  match '/' => 'blogs#show'
end

constraints(Subdomain) do
  match '/' => 'blogs#show'
end

ที่นี่ฉันกำลังเตรียมรหัสโดเมนย่อยที่มีอยู่ล่วงหน้า (อีกครั้งมันใช้งานได้ดี) พร้อมกับ stanza เพื่อตรวจสอบโดเมน ถ้าเซิร์ฟเวอร์นี้ตอบสนองต่อโดเมนนั้นและไม่ใช่เซิร์ฟเวอร์ที่ไซต์หลักทำงานให้ส่งต่อไปยังคอนโทรลเลอร์ที่ระบุ

และในขณะที่ดูเหมือนจะใช้งานได้ฉันก็ยังไม่ได้ทำงานทั้งหมด แต่ฉันคิดว่าปัญหานี้ได้รับการแก้ไขแล้ว


1
ขอบคุณมากสำหรับการแก้ไขของคุณแอรอน ตอนนี้ฉันกำลังเผชิญกับสถานการณ์เดียวกัน เป็นคำถามติดตามผลคุณจะทำให้เซิร์ฟเวอร์ของคุณยอมรับโดเมนใด ๆ ที่ส่งต่อไปยังเซิร์ฟเวอร์ได้อย่างไร ฉันคิดว่ามันจะเป็นการตั้งค่าในไฟล์. conf แต่ฉันไม่แน่ใจว่าอะไร ความช่วยเหลือใด ๆ ที่จะได้รับการชื่นชม!
เสียชีวิต

แอรอนฉันอยู่กับคุณ ฉันต้องการทำสิ่งเดียวกัน แต่ฉันไม่ต้องการฮาร์ดโค้ดโดเมน ฉันต้องการให้ทำทั้งหมดโดยใช้โปรแกรมโดยไม่มีไฟล์โซนและเว็บเซิร์ฟเวอร์จะรีสตาร์ท
Michael K Madison

1
ไมเคิลคุณต้องพลิกปัญหา ประกาศอย่างชัดเจนและระบุฮาร์ดโค้ดเส้นทางที่มีไว้สำหรับแอปพลิเคชันของคุณโดยเฉพาะ (เช่นการสมัครใช้งาน) ด้วยข้อ จำกัด ของโฮสต์หรือโดเมนย่อยจากนั้นให้ถือว่าเส้นทางหลักของคุณเป็น "โดเมนหรือโดเมนย่อยใด ๆ " ผู้ควบคุมของคุณมีหน้าที่ในการค้นหาโดเมนปัจจุบันหรือโดเมนย่อยและจับคู่กับลูกค้าที่เหมาะสม
Justin French

คำตอบ:


95

จริงๆแล้วมันง่ายกว่าใน Rails 3 ตามhttp://guides.rubyonrails.org/routing.html#advanced-constraints :

1) กำหนดคลาสข้อ จำกัด ที่กำหนดเองในlib/domain_constraint.rb:

class DomainConstraint
  def initialize(domain)
    @domains = [domain].flatten
  end

  def matches?(request)
    @domains.include? request.domain
  end
end

2) ใช้คลาสในเส้นทางของคุณด้วยไวยากรณ์บล็อกใหม่

constraints DomainConstraint.new('mydomain.com') do
  root :to => 'mydomain#index'
end

root :to => 'main#index'

หรือไวยากรณ์ตัวเลือกที่ล้าสมัย

root :to => 'mydomain#index', :constraints => DomainConstraint.new('mydomain.com')

6
คำตอบนี้ดูเหมือนจะง่ายกว่ามากสำหรับฉัน
Jared

7
นี่เป็นทางออกที่ยอดเยี่ยม มันทำงานอย่างไรกับสภาพแวดล้อมการพัฒนา?
superluminary

2
@superluminary จะทำงานได้ดีอย่างสมบูรณ์หากคุณตั้งค่าโดเมนท้องถิ่นสำหรับการพัฒนา (เช่นผ่าน/etc/hosts)
Leonid Shevtsov

7
หมายเหตุ: หากคุณใช้ Pow ในเครื่องและมี mydomain.com.dev ให้request.domainส่งกลับ. com.dev เปลี่ยนrequest.domainเป็นrequest.hostและทำงานได้อย่างสมบูรณ์
Eric Muyser

2
ฉันพบว่าฉันต้องสร้างเส้นทางที่ไม่มีชื่อเพื่อให้สามารถใช้งานได้มิฉะนั้นฉันจะได้รับInvalid route name, already in use: 'root'ข้อผิดพลาด ... ในการดำเนินการนี้ฉันเปลี่ยนเส้นทางเป็นroot :to => 'mydomain#index', as: nil
Just Lucky Really

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.