【问题标题】:Rails 4, has_many through, return a list of available items for a particular categoryRails 4,has_many through,返回特定类别的可用项目列表
【发布时间】:2016-11-19 07:10:30
【问题描述】:

我想知道在这种情况下是否应该创建一个类别控制器。目前我有一个具有#index 和#show 操作的项目控制器。我正在考虑在 items#index 操作中为特定类别添加过滤器 - 但从类别控制器执行似乎要容易得多。以下是我的关联,它们通过项目和类别之间的关系有效地建立了一个 has_many:

class Category < ActiveRecord::Base
    has_many :categorizations
    has_many :items, :through => :categorizations
end

class Item < ActiveRecord::Base
    has_many :categorizations
    has_many :categories, :through => :categorizations
end

class Categorization < ActiveRecord::Base
    belongs_to :item
    belongs_to :category
end

我需要我正在构建的 API 来返回“特定类别的可用项目列表”。从这样的类别控制器(我还没有)很容易做到这一点:

category.items

这样做是不是更好更安宁?或者我应该在我的 items#index 操作中创建一个过滤器,目前看起来像这样:

# Returns full list of items
def index
    @items = Item.all
    render json: @items
end

当然,如果您有任何更有效/符合最佳实践的想法 - 请告诉我!

谢谢!

编辑 - 一种解决方案:

我决定添加一个类别控制器,以便我可以使用以下相对路径访问特定类别的可用项目:

categories/:id/available_items

class CategoriesController < ApplicationController
    def available_items
        @available_items = Category.find(params[:id]).items.available
        render json: @available_items
   end
end

标准是返回与特定类别相关联且状态为“可用”的所有项目。

编辑:

我发现Item.where(category: 1) 没有返回归类在类别 1 下的所有项目。请参阅下面的 byebug 控制台输出:

    1: class ItemsController < ApplicationController
    2:   # Returns full list of items
    3:   def index
    4:     @items = Item.all
    5:      byebug
=>  6:   end
    7: 

(byebug) Item.where(category: 1)
  Item Load (0.6ms)  SELECT "items".* FROM "items" WHERE "items"."category" = 1
#<Item::ActiveRecord_Relation:0x007fb5d1a37f08>
(byebug) Category.find(1).items
  Category Load (0.7ms)  SELECT  "categories".* FROM "categories" WHERE "categories"."id" = $1 LIMIT 1  [["id", 1]]
  Item Load (1.7ms)  SELECT "items".* FROM "items" INNER JOIN "categorizations" ON "items"."id" = "categorizations"."item_id" WHERE "categorizations"."category_id" = $1  [["category_id", 1]]
#<ActiveRecord::Associations::CollectionProxy [#<Item id: 1, title: "Gorgeous Cotton Pants", description: "Dolor dicta suscipit aut cupiditate quia officiis ...", price: 73960, status: 0, published_date: "2016-07-14 05:35:49", created_at: "2016-07-17 05:15:07", updated_at: "2016-07-17 05:15:07", seller_id: 1>, #<Item id: 5, title: "Sleek Marble Shoes", description: "Qui mollitia corporis qui placeat. Reiciendis ea s...", price: 35146, status: 0, published_date: "2016-07-14 05:45:02", created_at: "2016-07-17 05:15:07", updated_at: "2016-07-17 05:15:07", seller_id: 1>, #<Item id: 7, title: "Rustic Concrete Lamp", description: "Sit odio non exercitationem. Atque non sapiente vo...", price: 82016, status: 2, published_date: "2016-07-13 00:00:00", created_at: "2016-07-17 05:15:07", updated_at: "2016-07-17 05:15:07", seller_id: 1>, #<Item id: 10, title: "Awesome Wooden Table", description: "Possimus consequatur nulla. Quidem molestiae volup...", price: 59519, status: 2, published_date: "2016-07-09 00:00:00", created_at: "2016-07-17 05:15:07", updated_at: "2016-07-17 05:15:07", seller_id: 1>, #<Item id: 12, title: "Lightweight Concrete Bag", description: "Amet ullam assumenda eligendi consectetur quae. Bl...", price: 72081, status: 2, published_date: "2016-07-16 00:00:00", created_at: "2016-07-17 05:15:07", updated_at: "2016-07-17 05:15:07", seller_id: 2>, #<Item id: 13, title: "Mediocre Plastic Computer", description: "Excepturi modi est non qui iusto. Molestiae offici...", price: 94357, status: 2, published_date: "2016-07-15 00:00:00", created_at: "2016-07-17 05:15:07", updated_at: "2016-07-17 05:15:07", seller_id: 2>, #<Item id: 15, title: "Incredible Plastic Bag", description: "Vel voluptas ducimus soluta atque voluptatem eum. ...", price: 15661, status: 2, published_date: "2016-07-14 00:00:00", created_at: "2016-07-17 05:15:07", updated_at: "2016-07-17 05:15:07", seller_id: 2>, #<Item id: 16, title: "Lightweight Iron Watch", description: "Id sequi rerum dolor sit sunt nemo laborum. Omnis ...", price: 65306, status: 4, published_date: "2016-07-11 00:00:00", created_at: "2016-07-17 05:15:07", updated_at: "2016-07-17 05:15:07", seller_id: 1>, #<Item id: 17, title: "Rustic Linen Chair", description: "Explicabo qui ad nihil. Voluptatem placeat autem. ...", price: 39752, status: 4, published_date: "2016-07-04 00:00:00", created_at: "2016-07-17 05:15:07", updated_at: "2016-07-17 05:15:07", seller_id: 1>, #<Item id: 18, title: "Mediocre Copper Car", description: "Minus qui ut est non vero saepe. Qui sed quos et v...", price: 87765, status: 4, published_date: "2016-07-05 00:00:00", created_at: "2016-07-17 05:15:07", updated_at: "2016-07-17 05:15:07", seller_id: 1>]>

【问题讨论】:

    标签: ruby-on-rails ruby api rest rails-activerecord


    【解决方案1】:

    您提出的两个解决方案都是有效的,但让我们看一些代码:

    选项 1 - Rails 默认值

    resources :categories do
      resources :items
    end
    
    # /categories/42/items/7
    

    Rails 会自行将其路由到 ItemsController,后者将负责处理传入的 category_id。如果您的应用程序架构/逻辑没有真正询问 em> 要以不同的方式完成,我将从这种方法开始。

    选项 2 —“显示类别”

    resources :categories, :items
    
    class CategoriesController < ApplicationController
      def index
        @categories = Category.all
      end
    
      def show
        @category = Category.includes(:items).find params[:id]
      end
    end
    

    如果显示控制器的概念自然会显示其项目,那么这种方法非常棒。鉴于多对多关系的典型性质,这可能不适用于您的情况,但这实际上取决于上下文。

    选项 3 - 三个整洁的控制器

    如果您发现您的 items#showitems#index 方法开始变得过于有条件,我会考虑更改您的路由并添加一个控制器

    class CategorizedItemsController < ApplicationController
      # ...
    end
    
    resources :categories
    resources :items
    scope '/categories/:category_id/' do 
      resources :items, controller: :categorized_items
    end
    

    这对于加入您项目的其他开发人员来说不太明显,并且开始使您的路线推理更具挑战性,所以我不会从它开始。不过,这是一个很好的解决方案,如果您发现现有的控制器层次结构无法在 RESTful 路由范围内表示您的操作,您应该毫不犹豫地采用它。

    干杯!

    【讨论】:

    • 谢谢 corey - 我正在添加更新以显示我现在使用的解决方案,也许你可以让我知道你的想法。
    • 让我无法选择选项 1 的一件事是,我不确定如何返回 category_id = x 的所有项目。有什么建议吗?
    • @matthewalexander 不过,您已经这样做了:Category.find(x).items。您也可以使用Item.where(category: x),这将允许您在Item 上使用其他范围(例如.available)。
    • 我发现 Item.where(category: x) 不起作用...我将发布 byebug 控制台输出以向您展示我的意思。
    • 决定为我的最后一个问题开一张新票。您对这个问题的回答非常感谢。 stackoverflow.com/questions/38423774/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-30
    • 1970-01-01
    • 2019-03-04
    • 2013-02-12
    • 2014-09-01
    • 1970-01-01
    相关资源
    最近更新 更多