Rails 5具有高级关系的RESTful API

时间:2016-12-14 12:21:18

标签: ruby-on-rails ruby routing ruby-on-rails-5

我有许多具有高级关系的资源(habtm / hm / hmt等等),你可以想象的一切,但现在是时候为这个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

对于此示例,我愿意通过创建Candidate来允许在UserSourcingAccount之间创建关系。

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希望将此路由发送给用户#remove和用户#add,我认为这是完全错误的。这些操作不得属于用户控制器。

加成:

创建属于其他2个模型的Account的多态路径应该是什么(具有在线验证)2个模型是Source,另一个是多态[Candidate,User] # for example,(他们是Sociable模型)

1 个答案:

答案 0 :(得分:3)

最佳做法是永远不要将资源嵌套到多个级别,并且只嵌套在需要嵌套的地方或提供上下文。

请记住,任何具有唯一ID或uid的记录都可以在没有上下文的情况下直接获取。因此,嵌套成员路线不必要地会使您的API过于复杂并且非常冗长。

javax.*

让我们以一个经典的微博应用为例:

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]

在某些情况下,如果资源应该在另一个上下文中创建,您将希望嵌套以嵌套创建操作:

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