inherited_resources - лучшие практики для отсутствующей родительской модели - PullRequest
0 голосов
/ 15 июля 2011

Возможно, вы видели / читали Railscast / Asciicast о поддоменах в Rails 3 .Я хотел бы, чтобы вы спросили о передовых методах реализации поведения приложения, когда родитель (в этой статье: «блог») не найден.Позвольте мне объяснить.

blog1.example.com/articles # it's normal situation
example.com/articles # abnormal situation. 

Во втором примере блог не найден, но маршруты статей по-прежнему доступны.Я знаю, я могу использовать что-то вроде этого ...

def rescue_action(exception)
  case exception
    when ActiveRecord::RecordNotFound
      return redirect_to blogs_path, :status => :moved_permanently
  end
  super
end 

... но так ли это "путь Rails"?Любая идея / комментарий по этому поводу?

1 Ответ

0 голосов
/ 12 августа 2011

В данном случае я ограничил маршрутизацию на основе поддоменов или их отсутствия.В этом случае вы можете легко иметь маршруты, которые работают только на поддоменах, что приведет к ошибке маршрутизации (404), если кто-то попытается получить доступ к этому же маршруту без поддоменов.

Так, например:

rout.rb

Backend::Application.routes.draw do

  constraints AppDomainRoutes.new do

    # signup paths
    get   "/signup" => "accounts#new", as: "signup"
    post  "/signup" => "accounts#create", as: "signup"

    # root
    root to: "accounts#new"
  end

  constraints AccountDomainRoutes.new do

    # password reset paths
    get   "/reset_password/:password_reset_token" => "reset_passwords#edit", as: "reset_user_password"
    put   "/reset_password/:password_reset_token" => "reset_passwords#update", as: "reset_user_password"

    # websites
    resources :websites

    # root
    root to: "websites#new"
  end

  # request password reset paths
  get   "/reset_password" => "reset_passwords#new", as: "reset_password_request"
  post  "/reset_password" => "reset_passwords#create", as: "reset_password_request"

  # login paths
  get "/login"   => "sessions#new",      as: "login"
  post "/login"  => "sessions#create",   as: "login"

  # logout paths
  get "/logout"    => "sessions#destroy",  as: "logout"
  delete "/logout" => "sessions#destroy",  as: "logout"


end

А затем в lib / маршруты:

app_domain_routes.rb

class AppDomainRoutes
  def matches?(request)
    request.subdomain.blank? || request.subdomain == "www"
  end
end

account_domain_routes.rb

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

Теперь /signup доступен только из основного домена приложения www.mydomain.com или mydomain.com , а /websites/new доступен только с *. Mydomain.com .Но /login все еще доступен в обеих ситуациях, для удобства.

Очевидно, что это не решает проблему посещения invalid.mydomain.com, когда invalid фактически не является учетной записью в базе данных.

Для этого вы возвращаетесь к application_controller.rb и обрабатываете там перенаправление, например:

application_controller.rb

class ApplicationController < ActionController::Base
  protect_from_forgery
  before_filter :redirect_unknown_account

  private

  # returns current subdomain (account.subdomain) or nil
  def account_subdomain
    @account_subdomain ||= request.subdomain if request.subdomain.present? && request.subdomain != "www"
  end

  def current_account
    @current_account ||= Account.find_by_username(account_subdomain) if account_subdomain
  end

  def redirect_unknown_account
    if account_subdomain && ! current_account
      redirect_to signup_url(host: app_domain), alert: "This account does not exist."
    end
  end

  def account_domain
    @account_domain ||= "#{current_account.username}.#{app_domain}" if current_account
  end

  def app_domain
    @app_domain ||= "mydomain.com"
  end

end
...