ruby-on-rails - 具有高级关系的 Rails 5 RESTful API

标签 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

对于此示例,我愿意通过创建 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 想要将它路由到 users#remove 和 users#add,我认为这是完全错误的。这些操作不得属于用户 Controller 。

奖励:

创建属于其他 2 个模型(具有存在验证)的 Account 的多态路由看起来应该是什么,这 2 个模型是 Source,另一个是多态的 [Candidate,User] # 例如,(他们是Sociable模型)

最佳答案

最佳做法是永远不要*嵌套资源超过一层,并且只在需要嵌套或提供上下文的地方嵌套。

请记住,任何具有唯一 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]

使用模块选项可以让我们区分“基本资源”的 Controller 及其嵌套表示:

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

关于ruby-on-rails - 具有高级关系的 Rails 5 RESTful API,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41142529/

相关文章:

java - 索引操作 Java Spring Controller

ruby-on-rails - 处理 heroku 上不存在的表的 drop_table 迁移

ruby-on-rails - 看不懂Ruby的神奇

ruby - 查找以 "j"开头并包含 "w"的 4 个字母字符串的所有排列?

ruby - 处理 ruby​​ 中的默认异常

ruby-on-rails - 如何在 Rails 4 中将一组资源路由别名或重写到另一个命名空间?

ruby-on-rails - 在 Rails 中处理多个根路径和范围

路由组件的 Angular 2 "slide in animation"

ruby-on-rails - 如何优化此事件记录查询?