Managing multiple domains in a rails application error: "NameError (uninitialized constant #<Class:0x0000563d7bf62250>::Heroku):"
Managing multiple domains in a rails application error: "NameError (uninitialized constant #<Class:0x0000563d7bf62250>::Heroku):"
在我的 rails 应用程序中,我正在尝试创建一个预订表格,外部各方(parks
)可以将他们的客户指向相应公园进行预订。预订表格适用于子域 book
的 url/route
https://book.myapp.com/en/parks/:park_id/park_availability
目标
我想用 park
的网站替换我的域 (myapp.com
),这样我得到
https://book.parkapp.com/en/park_availability
很遗憾,我收到了错误消息
创世园
NameError (uninitialized constant #<Class:0x0000563d7bf62250>::Heroku):
使用现有公园时
{park.website}'s server IP address could not be found.
概述尝试的方法
Park
有一个 website
列。在 routes.rb
中,我尝试设置约束并将它们应用于 park_availability
操作。
- 在
Park
模型中,一旦公园被保存,我尝试将域 (Park.website
) 添加到我的 Heroku 应用程序。
- 在我的
Park controller
中,我尝试在 park_availability
操作之前找到 @park
。
代码
routes.rb
class CustomDomainConstraint
# Implement the .matches? method and pass in the request object
def self.matches? request
matching_site?(request)
end
def self.matching_site? request
# handle the case of the user's domain being either www. or a root domain with one query
if request.subdomain == 'www'
req = request.host[4..-1]
else
req = request.host
end
# first test if there exists a Site with a domain which matches the request,
# if not, check the subdomain. If none are found, the the 'match' will not match anything
Park.where(:website => req).any?
end
end
Rails.application.routes.draw do
resources :parks do
match ':website/park_availability' => 'parks#park_availability', on: :member, :constraints => CustomDomainConstraint, via: :all
end
end
park.rb
class Park < ApplicationRecord
after_save do |park|
heroku_environments = %w(production staging)
if park.website && (heroku_environments.include? Rails.env)
added = false
heroku = Heroku::API.new(api_key: ENV['HEROKU_API_KEY'])
heroku.get_domains(ENV['APP_NAME']).data[:body].each do |domain|
added = true if domain['domain'] == park.website
end
unless added
heroku.post_domain(ENV['APP_NAME'], park.website)
heroku.post_domain(ENV['APP_NAME'], "www.#{park.website}")
end
end
end
parks_controller.rb
class ParksController < ApplicationController
before_action :find_park, only:[:park_availability]
def park_availability
#working code...
end
private
def find_park
# generalise away the potential www. or root variants of the domain name
if request.subdomain == 'www'
req = request.host[4..-1]
else
req = request.host
end
# test if there exists a Park with the requested domain,
@park = Park.find_by(website: req)
# if a matching site wasn't found, redirect the user to the www.<website>
redirect_to :back
end
end
要绕过问题中的错误,您可以尝试将类名写成 ::Heroku
,这将使 ruby 在正确的范围内查找它。
但是 Heroku legacy api has been disabled, so you should use their new platform-api:
heroku = PlatformAPI.connect(ENV['HEROKU_API_KEY']) # note that you may also have to use a new key
domains = heroku.domain.list(ENV['APP_NAME'])
...
heroku.domain.create(ENV['APP_NAME'], ...)
还可以使用 domain.info
api 方法来检查域是否存在,而不是获取所有不需要的域。
请记住,回调不是进行任何外部调用的最佳位置:如果 api 调用由于某种原因失败(临时网络问题、api 中断、服务器重启等) - 整个交易将被回滚,项目将不会被保存,你可以松散数据。更好的方法是在那里排队后台作业,稍后将处理域,如果需要可以重试等等。
在我的 rails 应用程序中,我正在尝试创建一个预订表格,外部各方(parks
)可以将他们的客户指向相应公园进行预订。预订表格适用于子域 book
https://book.myapp.com/en/parks/:park_id/park_availability
目标
我想用 park
的网站替换我的域 (myapp.com
),这样我得到
https://book.parkapp.com/en/park_availability
很遗憾,我收到了错误消息 创世园
NameError (uninitialized constant #<Class:0x0000563d7bf62250>::Heroku):
使用现有公园时
{park.website}'s server IP address could not be found.
概述尝试的方法
Park
有一个website
列。在routes.rb
中,我尝试设置约束并将它们应用于park_availability
操作。- 在
Park
模型中,一旦公园被保存,我尝试将域 (Park.website
) 添加到我的 Heroku 应用程序。 - 在我的
Park controller
中,我尝试在park_availability
操作之前找到@park
。
代码
routes.rb
class CustomDomainConstraint
# Implement the .matches? method and pass in the request object
def self.matches? request
matching_site?(request)
end
def self.matching_site? request
# handle the case of the user's domain being either www. or a root domain with one query
if request.subdomain == 'www'
req = request.host[4..-1]
else
req = request.host
end
# first test if there exists a Site with a domain which matches the request,
# if not, check the subdomain. If none are found, the the 'match' will not match anything
Park.where(:website => req).any?
end
end
Rails.application.routes.draw do
resources :parks do
match ':website/park_availability' => 'parks#park_availability', on: :member, :constraints => CustomDomainConstraint, via: :all
end
end
park.rb
class Park < ApplicationRecord
after_save do |park|
heroku_environments = %w(production staging)
if park.website && (heroku_environments.include? Rails.env)
added = false
heroku = Heroku::API.new(api_key: ENV['HEROKU_API_KEY'])
heroku.get_domains(ENV['APP_NAME']).data[:body].each do |domain|
added = true if domain['domain'] == park.website
end
unless added
heroku.post_domain(ENV['APP_NAME'], park.website)
heroku.post_domain(ENV['APP_NAME'], "www.#{park.website}")
end
end
end
parks_controller.rb
class ParksController < ApplicationController
before_action :find_park, only:[:park_availability]
def park_availability
#working code...
end
private
def find_park
# generalise away the potential www. or root variants of the domain name
if request.subdomain == 'www'
req = request.host[4..-1]
else
req = request.host
end
# test if there exists a Park with the requested domain,
@park = Park.find_by(website: req)
# if a matching site wasn't found, redirect the user to the www.<website>
redirect_to :back
end
end
要绕过问题中的错误,您可以尝试将类名写成 ::Heroku
,这将使 ruby 在正确的范围内查找它。
但是 Heroku legacy api has been disabled, so you should use their new platform-api:
heroku = PlatformAPI.connect(ENV['HEROKU_API_KEY']) # note that you may also have to use a new key
domains = heroku.domain.list(ENV['APP_NAME'])
...
heroku.domain.create(ENV['APP_NAME'], ...)
还可以使用 domain.info
api 方法来检查域是否存在,而不是获取所有不需要的域。
请记住,回调不是进行任何外部调用的最佳位置:如果 api 调用由于某种原因失败(临时网络问题、api 中断、服务器重启等) - 整个交易将被回滚,项目将不会被保存,你可以松散数据。更好的方法是在那里排队后台作业,稍后将处理域,如果需要可以重试等等。