Ruby Rails 路径按用户显示所有项目

Ruby Rails Path Show All Item by User

这里是 RoR 初学者。我正在尝试实现一个页面 'My Products' 来显示当前用户添加的所有产品。目前我已经将 'All Products' 页面设置为我的索引根 "products#index"。我的产品有控制器,但我的用户没有控制器,因为我使用的是 Devise。我有几个问题,我还是没答对。

因为目前

产品

belongs_to :user

用户

has_many :products

路线

devise_for :users
resources :products

我有rake路线

new_user_session      GET    /users/sign_in(.:format)                  devise/sessions#new
         user_session POST   /users/sign_in(.:format)                  devise/sessions#create
 destroy_user_session DELETE /users/sign_out(.:format)                 devise/sessions#destroy
        user_password POST   /users/password(.:format)                 devise/passwords#create
    new_user_password GET    /users/password/new(.:format)             devise/passwords#new
   edit_user_password GET    /users/password/edit(.:format)            devise/passwords#edit
                      PATCH  /users/password(.:format)                 devise/passwords#update
                      PUT    /users/password(.:format)                 devise/passwords#update
cancel_user_registration GET    /users/cancel(.:format)                   devise/registrations#cancel
    user_registration POST   /users(.:format)                          devise/registrations#create
new_user_registration GET    /users/sign_up(.:format)                  devise/registrations#new   edit_user_registration GET    /users/edit(.:format)                     devise/registrations#edit
                      PATCH  /users(.:format)                          devise/registrations#update
                      PUT    /users(.:format)                          devise/registrations#update
                      DELETE /users(.:format)                          devise/registrations#destroy
products              GET    /products(.:format)                       products#index
                      POST   /products(.:format)                       products#create
          new_product GET    /products/new(.:format)                   products#new
         edit_product GET    /products/:id/edit(.:format)              products#edit
              product GET    /products/:id(.:format)                   products#show
                      PATCH  /products/:id(.:format)                   products#update
                      PUT    /products/:id(.:format)                   products#update
                      DELETE /products/:id(.:format)                   products#destroy

目前我的想法是:

创建一个 UserController 使 @user = User.all 然后因为通过关联我可以使用 @user.product。 (我看到有人说我不应该因为设计而创建新的控制器?)但是,我在执行之前尝试使用 rails 控制台进行测试。

 product = Product.first
 product.user #here I get all details about user

 user = User.first
 user.product #here I get error. Why it works for product to find user but not both ways?

接下来,这让我想知道如何创建配置路由以获取路径 /users/:id/products 。我应该使用嵌套资源吗?

下一个问题,我试过

resources :users do
  resources :products
end

resources :products

我又输入了佣金路线。我很困惑

 user_products GET    /users/:user_id/products(.:format)          products#index
 products GET    /products(.:format)                         products#index 

问题:

  1. 2 个路径可以有相同的 Controller#Action 吗?
  2. user_products_path 和 products_path 是 2 个不同的路径,其中 user_products_path 代表用户的产品。 products_path代表所有产品

很抱歉 post.I 真的很想澄清那些事情。如果你能帮忙,非常感谢!! :)

user.product #here I get error. Why it works for product to find user but not both ways?

作为User has_many :products,您需要使用正确的关联名称作为:

 user.products # it will give you all products of an user

Can 2 path has the same Controller#Action?

简而言之,是的。您可以在 route.rb 中明确指定控制器和操作名称,例如:

get 'users/:id/products' => 'products#index', :as => :user_products_path

注意在你的情况下,默认情况下它也会进入products#index

user_products_path and products_path are 2 different path where user_products_path represents user's product. and products_path represents all products

没错,绝对没问题。当您使用 devise 时,您不需要使用来自 URL 即 users/:id/productsid 参数。您可以直接从 current_user 获取用户,这在安全性方面也更好。请记住,如果您拥有可以查看每个用户详细信息的管理员角色,那么在这种情况下您将需要管理 id

因为您刚刚起步,所以我将通过易于阅读的逻辑使这个示例保持简单。但是,有更好的方法来配置和优化它,这样您就不会依赖控制器中的 if 语句。

class ProductsController < ApplicationController
  def index
    if params[:user_id]
      @user = User.find(params[:user_id])
      @products = @user.products.all
    else
      @products = Product.all
    end
  end
end

这是不好的做法的一个原因是您依赖 user_id 参数是有效的。如果 user_id 参数无效,则第二行 @products = @user.products.all 将 return undefined method for Nil class.

此外,在您看来,如果您引用 @user,那么如果您只是列出所有产品,则会出现错误。

此外,如果任何人知道或试图猜测用户的 id

,则任何人都可以看到任何人的产品,因此没有任何安全措施。

但是,这应该适用于您的实例。您可能还需要考虑,如果存在 user_id,则调用 current_user.products.all,这样它只会 return 当前用户的产品,而不是特定的 user_id。但是,这实际上取决于您如何设计应用程序来确定最佳路径。

我通常会做的是,如果 /products 路由应该用于管理级别,我会 namespace 它并在命名空间周围设置适当的安全性,这样它就不允许一般用户可以访问它,而只有网站管理员才能访问它。