Как определить маршруты, которые включают имя динамической организации в Rails - PullRequest
0 голосов
/ 31 мая 2018

Я создаю SaaS-приложение Rails 5.2, которое позволяет пользователям принадлежать ко многим «организациям».Пользователи будут видеть контент только для своей текущей активной организации.

Я начал использовать поддомен, но после небольшого исследования решил пока избегать их .

Мой новый подход (чтобы дать пользователю понять, какую организацию он использует, поддерживает обмен ссылками, историю браузера и т. Д.) Состоит в том, чтобы вставить название организации в путь.Например:

https://app.example.com/foo/posts   # Posts for org "foo"
https://app.example.com/foo/posts/7 # Post for org "foo"
https://app.example.com/bar/posts   # Posts for org "bar"
https://app.example.com/settings    # General account settings
https://app.example.com/signin      # Sign in

Моя проблема в том, как сделать это с маршрутами Rails?Я пытался использовать динамическую область:

scope ':org' do
  resources :posts
end

Результаты с ошибками, как:

No route matches {:action=>"show", :controller=>"posts", :org=>#<Organization id: 1, name: "My Organization", ...}, missing required keys: [:id]

Для кода:

# layouts/application.html.erb
<%= link_to post, post, class: 'dropdown-item' %>

Любые предложения о том, какнастроить маршруты для поддержки этого варианта использования?

1 Ответ

0 голосов
/ 31 мая 2018

Используйте макрос ресурсов:

Rails.application.routes.draw do
  resources :posts, except: [:new, :create]
  resources :organizations, path: '/', only: [] do
    resources :posts, module: :organizations, only: [:new, :index, :create]
  end
end

$ rails routes:

               Prefix Verb   URI Pattern                           Controller#Action
                posts GET    /posts(.:format)                      posts#index
            edit_post GET    /posts/:id/edit(.:format)             posts#edit
                 post GET    /posts/:id(.:format)                  posts#show
                      PATCH  /posts/:id(.:format)                  posts#update
                      PUT    /posts/:id(.:format)                  posts#update
                      DELETE /posts/:id(.:format)                  posts#destroy
   organization_posts GET    /:organization_id/posts(.:format)     organizations/posts#index
                      POST   /:organization_id/posts(.:format)     organizations/posts#create
new_organization_post GET    /:organization_id/posts/new(.:format) organizations/posts#new

С помощью опции module: вы можете настроить отдельный контроллер для вложенного контекста:

# app/controllers/organizations/posts_controller.rb
class Organizations::PostsController < ApplicationController

  before_action :set_organization!

  # Index for posts belonging to a specific organization
  # GET    /:organization_id/posts
  def index
    @posts = @organization.posts
  end

  # GET    /:organization_id/posts/new
  def new
    @post = @organization.posts.new
  end

  # POST   /:organization_id/posts
  def create
    @post = Post.new(post_params)

    if @post.save
      redirect_to @post, notice: 'Post was successfully created.'
    else
      render :new
    end
  end

  private
    def set_organization!
      @organization = Organization.includes(:posts)
                                  .find_by!(name: params[:organization_id])
    end 

    def post_params
      params.require(:post).permit(:title)
    end
end

class PostsController < ApplicationController
  before_action :set_post, only: [:show, :edit, :update, :destroy]

  # Index for posts belonging to all organizations
  # GET /posts
  def index
    @posts = Post.all
  end

  # GET /posts/1
  def show
  end

  # GET /posts/1/edit
  def edit
  end

  # PATCH/PUT /posts/1
  def update
    if @post.update(post_params)
      redirect_to @post, notice: 'Post was successfully updated.'
    else
      render :edit
    end
  end

  # DELETE /posts/1
  def destroy
    @post.destroy
    redirect_to posts_url, notice: 'Post was successfully destroyed.'
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_post
      @post = Post.find(params[:id])
    end

    # Only allow a trusted parameter "white list" through.
    def post_params
      params.require(:post).permit(:title)
    end
end

Однако при создании маршрутов, начинающихся с динамического сегмента, следует соблюдать осторожность - маршруты имеют приоритет в том порядке, в котором они определены, а маршрут, начинающийся с динамического сегмента, будет «жадным»."и проглотить другие маршруты, если они не определены первыми.

...