2016-12-14 67 views
2

我有先進的關係許多資源(HABTM/HM/HMT等),所有你能想象,但現在它的時間來寫這個API一個美麗的路由。 問題是,我不能鰭約嵌套資源+先進的RO關係做我的路由的最佳實踐,這裏就是我試圖做的事:Rails的5擁有先進的REST風格的關係API

這裏是我的模型與相關關係

# app/models/candidate.rb 
class Candidate < ApplicationRecord 
    include Sociable, Locatable 

    belongs_to :user 
    has_many :sourcing_accounts 
    has_many :accounts, through: :sourcing_accounts 
    has_many :users, through: :sourcing_accounts 
end 

# app/models/sourcing_account.rb 
class SourcingAccount < ApplicationRecord 
    belongs_to :account 
    belongs_to :candidate 
    belongs_to :user 
end 

# app/models/user.rb 
class User < ApplicationRecord 
    include Sociable 

    has_many :candidates 
    has_many :campaigns 
    has_many :sourcing_account 
end 

在這個例子中,我願意允許通過創建SourcingAccount創建CandidateUser之間的關係。

resources :candidates do 
    resources :accounts 
    resources :users, only: [:index] do 
    post :remove 
    post :add 
    end 
end 

它產生:

v1_candidate_user_remove POST /v1/candidates/:candidate_id/users/:user_id/remove(.:format) api/v1/users#remove {:subdomain=>"api", :format=>:json} 
    v1_candidate_user_add POST /v1/candidates/:candidate_id/users/:user_id/add(.:format) api/v1/users#add {:subdomain=>"api", :format=>:json} 

我沒發現這事。有最佳做法嗎? 如果不是,您認爲這種情況最好的是什麼?

沒有精度,Rails的希望路線這#刪除用戶和用戶#補充,我認爲這是完全錯誤的。這些操作不得屬於用戶控制器。

獎勵:

應該看起來像一個多態的路線是什麼創造一個Account屬於其他2款(與存在驗證)2個模型是Source,另一種是多態的[Candidate,User] # for example,(他們是Sociable型號)

回答

3

最好的做法是永遠不會*巢資源不止一個級別,只有窩在那裏築巢是必要的,或者提供上下文。

比任何紀錄記住一個唯一的ID或UID可以直接沒有上下文中獲取。所以嵌套成員路由不必要的會使你的API過於複雜,真的很羅嗦。

DELETE /as/:id 
is a lot better than 
DELETE /as/:a_id/bs/:b_id/c/:id # Are you kidding me! 

比方說拿一個經典的微博應用程序爲例:

class User 
    has_many :posts, foreign_key: 'author_id' 
    has_many :comments 
end 

class Post 
    belongs_to :author, class_name: 'User' 
end 

class Comment 
    belongs_to :user 
    belongs_to :post 
end 

你可以聲明路線爲:

resources :users do 
    scope module: :users do 
    resources :posts, only: [:index] 
    resources :comments, only: [:index] 
    end 
end 

resources :posts do 
    resources :comments, module: :posts, only: [:index, :create] 
end 

resources :comments, only: [:index, :destroy, :update] 

使用模塊選項讓我們destinguish控制器對之間「基礎資源」,其嵌套表示:

class API::V1::PostsController < ApplicationController 
    # GET /api/v1/posts 
    def index 
    @posts = Post.all 
    end 

    def show 
    # ... 
    end 
    def destroy 
    # ... 
    end 
    def update 
    # ... 
    end 
end 

# Represents posts that belong to a user 
class API::V1::Users::PostsController < ApplicationController 
    # GET /api/v1/users/:user_id/posts 
    def index 
    @user = User.eager_load(:posts).find(params[:user_id]) 
    respond_with(@user.posts) 
    end 
end 

在某些情況下,你會想窩巢的創建操作以及資源是否應該在另一個上下文中創建:

class API::V1::Posts::CommentsController < ApplicationController 
    # PATCH /api/v1/posts/:post_id/comments 
    def create 
    @post = Post.find(params[:post_id]) 
    @comment = @post.comments.create(comment_params) 
    respond_with(@comment) 
    end 

    # GET /api/v1/posts/:post_id/comments 
    def index 
    @post = Post.eager_load(:comments).find(params[:post_id]) 
    respond_with(@post.comments) 
    end 
end 
+1

還規範CRUD操作(顯示,索引,創建,銷燬,更新)可以增加額外的動詞,但是如果你曾經使用'add'或'remove'這樣的同義詞,或者用'def things'列舉或嵌套資源。你做錯了。 – max

+0

感謝您的明確解釋,但是在最後一個示例中,您將如何使用2個上下文(模型屬於2個其他)來包裝創建動作?就像我在帖子中的紅利問題一樣。如何在2個父母需要同時在場時創建關係對象 –

+1

您不需要。使用最重要的模型作爲上下文,並將其他關係作爲參數傳遞。 – max