如何为 has_many 创建控制器和视图并通过 ruby 中的关系创建 rails

How to create controller and views for has_many and through relationship in ruby on rails

请放轻松,因为我只是一个初学者,在过去的两天里,我一直在为这个问题伤脑筋。总而言之,我有一个 user 和 productplan ,当用户选择某个产品计划(单选按钮或复选框)时,我希望将当前用户 ID 和所选产品 ID 存储在名为 userproducts 的连接 table 中 但由于某种原因我无法存储数据,我不知道我哪里出错了,感谢任何帮助,谢谢。

型号:

class User < ActiveRecord::Base
  has_many :userproducts
  has_many :productplans, :through=>:userproducts
end

class productplan < ApplicationRecord
  has_many :userproducts
  has_many :users, :through => :userproducts
end

class Userproduct < ApplicationRecord
  belongs_to :user
  belongs_to :productplan
end

ProductPlan 控制器:

class ProductPlanController < ApplicationController
before_action :authenticate_user!
def new 
    @user=User.new
  end  
end

def create
  @user = User.create(user_params)
  if @user.save
    render :action => 'index'
  else
    render :action =>'new'
  end
private 
def user_params
  params.require(:user).permit(:productplan_ids => [])
end
end

观看次数: productplan/_form.html.erb

<%= form_for @user,:url=> productplan_index_path,:method => :post do 
|f|%>
<%= f.collection_check_boxes :productplan_ids, ProductPlan.all, :id, 
:productplan_name %>
<%= f.submit %>
<% end %>

由于控制器上的示例和关于 has_many 的视图较少,我很确定我在其中有很多错误。另外,当我尝试提交表单时,我得到了这个日志:

enterStarted POST "/Productplan" for 127.0.0.1 at 2017-11-28 11:08:29 -0600
Processing by ProductPlanController#create as HTML
Parameters 
{"utf8"=>"✓","authenticity_token"=>
"mi9RwHCLPKItXai67t5iX0RYrDoE6TN9T
iZzJFYELbKVDlHbhpeNmOC0q2gu1iXyWNaUqGSEsPrBEjcUSE2yYw==", "user"= >
{"productsku_ids"=>["", "4", "7"]}, "commit"=>"Create User"}
User Load (1.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" =  
ORDER BY "users"."id" ASC LIMIT   [["id", 3], ["LIMIT", 1]]
ProductPlan Load (2.6ms)  SELECT "productplans".* FROM "productplans" WHERE 
"productplans"."id" IN (4, 7)
(0.5ms)  BEGIN
Provider Load (0.5ms)  SELECT  "providers".* FROM "providers" WHERE 
"providers"."id" =  LIMIT   [["id", 1], ["LIMIT", 1]]
CACHE Provider Load (0.0ms)  SELECT  "providers".* FROM "providers" WHERE 
"providers"."id" =  LIMIT   [["id", 1], ["LIMIT", 1]]
(0.6ms)  ROLLBACK
Rendering ups/new.html.erb within layouts/application
ProductPlan Load (0.9ms)  SELECT "productplans".* FROM "productplans"
Rendered productplans/_form.html.erb (4.6ms)
Rendered productplans/new.html.erb within layouts/application (6.4ms)
Rendered _navbar.html.erb (0.7ms)
Completed 200 OK in 191ms (Views: 102.1ms | ActiveRecord: 14.6ms) here

由于某种原因它回滚了,我也需要获取当前用户。

dependent_new GET    /dependent/new(.:format)              dependent#new
    dependent_create GET    /dependent/create(.:format)           dependent#create
        summary_root GET    /summary/index(.:format)              summary#index
          home_plans GET    /home/plans(.:format)                 home#plans
              thanks GET    /thanks(.:format)                     charges#thanks
  authenticated_root GET    /                                     home#roothome
    productplan_index GET    /productplan(.:format)                 productplan#index
                     POST   /productplan(.:format)                 productplan#create
      new_productplan GET    /productplan/new(.:format)             productplan#new
     edit_productplan GET    /productplan/:id/edit(.:format)        productplan#edit
          productplan GET    /productplan/:id(.:format)             productplan#show
                     PATCH  /productplan/:id(.:format)             productplan#update
                     PUT    /productplan/:id(.:format)             productplan#update
                     DELETE /productplan/:id(.:format)             productplan#destroy
        userproducts GET    /userproducts(.:format)               userproducts#index
                     POST   /userproducts(.:format)               userproducts#create
     new_userproduct GET    /userproducts/new(.:format)           userproducts#new
    edit_userproduct GET    /userproducts/:id/edit(.:format)      userproducts#edit
         userproduct GET    /userproducts/:id(.:format)           userproducts#show
                     PATCH  /userproducts/:id(.:format)           userproducts#update
                     PUT    /userproducts/:id(.:format)           userproducts#update
                     DELETE /userproducts/:id(.:format)           userproducts#destroy
                 ups POST   /ups(.:format)                        ups#create
              new_up GET    /ups/new(.:format)                    ups#new
                root GET    /                                     home#index
    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
   new_user_password GET    /users/password/new(.:format)         devise/passwords#new
  edit_user_password GET    /users/password/edit(.:format)        devise/passwords#edit
       user_password PATCH  /users/password(.:format)             devise/passwords#update
                     PUT    /users/password(.:format)             devise/passwords#update
                     POST   /users/password(.:format)             devise/passwords#create

所以我按照@jvillian 的要求修改了我的代码,但问题仍然存在,这是我的新代码。 请注意我将用户产品重命名为 ups,

型号:

class User < ActiveRecord::Base
 has_many :ups
 has_many :productplans, through: :ups
end

class productplan < ApplicationRecord
 has_many :ups
 has_many :users, :through => :ups
end

class Up < ApplicationRecord
 belongs_to :user
 belongs_to :productplan
end

Ups 控制器:

class UpsController < ApplicationController
before_action :authenticate_user!

def create
 current_user.productplans<<Productplan.where(id: productplans_ids)
 render :action => 'index'
end

private

def productplan_ids
 params.require(:up).permit(productplan_ids:[])
end
end

观看次数ups/_form.html.erb

<%= form_for :up,:url=> ups_path do |f| %>
<%= f.collection_check_boxes :productplan_ids, Productplan.all, :id, 
:productplan_name %>
<%= f.submit %>
<% end %>

日志:

Started GET "/ups" for 127.0.0.1 at 2017-11-28 14:43:50 -0600
Processing by UpsController#index as HTML
User Load (1.6ms)  SELECT  "users".* FROM "users" WHERE "users"."id" =  
ORDER BY "users"."id" ASC LIMIT   [["id", 3], ["LIMIT", 1]]
Rendering ups/index.html.erb within layouts/application
Productplan Load (0.7ms)  SELECT "productplans".* FROM "productplans"
Rendered ups/_form.html.erb (42.5ms)
Rendered ups/index.html.erb within layouts/application (47.7ms)
Rendered _navbar.html.erb (0.9ms)
Completed 200 OK in 347ms (Views: 235.0ms | ActiveRecord: 15.0ms)


Started POST "/ups" for 127.0.0.1 at 2017-11-28 14:43:53 -0600
Processing by UpsController#create as HTML
Parameters: {"utf8"=>"✓", 
"authenticity_token"=>"g7lLydleU7J14G7N9avWSK87E4BbkPQ9sdL
Q9X2bbSCMmEvSL0LiiLgJbR81o5Hls7UrEjv9d7o+5pTFY9Ly8Q==", "up"=>
{"productplan_ids"=>["", "4"]}, "commit"=>"Save Up"}
User Load (1.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" =  
ORDER BY "users"."id" ASC LIMIT   [["id", 3], ["LIMIT", 1]]
Productplan Load (0.7ms)  SELECT "productplans".* FROM "productplans" WHERE 
"productplans"."id" =   [["id", nil]]
(0.4ms)  BEGIN
(0.3ms)  COMMIT
Rendering ups/index.html.erb within layouts/application
Productplan Load (0.6ms)  SELECT "productplans".* FROM "productplans"
Rendered ups/_form.html.erb (4.9ms)
Rendered ups/index.html.erb within layouts/application (7.9ms)
Rendered _navbar.html.erb (1.0ms)
Completed 200 OK in 201ms (Views: 183.4ms | ActiveRecord: 3.0ms)

route.rb

devise_scope :user do
# write all your routes inside this block
resources :productplan
resources :ups
end

Ups中仍然没有插入数据table,也没有报错。虽然根据日志文件它没有回滚,但问题仍然存在。

更新:从 OP

修改代码后

更近了!

如您所见:

Productplan Load (0.7ms)  SELECT "productplans".* FROM "productplans" WHERE "productplans"."id" =   [["id", nil]]

我们没有得到 productplan_ids 完全正确(如 nil 所示)。如果您在控制台中执行以下操作:

> params = ActionController::Parameters.new(up: {productplan_ids: ["","4"]})
> params.require(:up).permit(productplan_ids: [])
 => {"productplan_ids"=>["", "4"]}

您可以看到 productplan_ids 方法返回 hash(好吧,不完全是,但现在已经足够接近了)。但是,您需要 :productplan_ids 键的值。所以,试试:

def productplan_ids
  params.require(:up)[:productplan_ids]
end

哪个应该给你:

> params.require(:up)[:productplan_ids]
 => ["", "4"]

您正在寻找的 array

原始答案

我打算尝试一下,但这会很艰难。

好吧,让我们假设:

  • 您有一个登录用户可以通过 current_user 在您的 create 操作中使用(看起来您正在使用 Devise?)
  • 您已经创建了 ProductPlans
  • routes.rb 中,你有 resources :user_products(不是 userproducts,请参阅稍后的注释...)

您的 form_for 应如下所示:

<%= form_for :user_product, user_products_path do |f| %>
  <%= f.collection_check_boxes :product_plan_ids, ProductPlan.all, :id, :product_plan_name %>
  <%= f.submit %>
<% end %>

注意:您可以使用符号 :user_product 而不是实例变量 @user 因为您没有将任何表单字段基于 @user.

注意:表单会自动执行 post,因此您无需指定 method

然后,UserProductsController(不是 ProductPlanController,因为你要创建一个或多个 user_products 而不是 product_plans)应该类似于:

class UserProductsController < ApplicationController

  def create
    current_user.product_plans << ProductPlan.where(id: product_plan_ids)
    render action: some_success_condition ? 'index' : 'new'
  end

  private

  def product_plan_ids
    params.require(:user_product).permit(product_plan_ids: [])
  end

end

注意:您可能不需要 new 操作,因为您实际上不需要实例化任何东西(至少不需要基于您展示的任何东西)。

注意:您需要弄清楚 some_success_condition 是什么。但肯定不是@user.save。因为您正在创建 user_products,而不是 user

此外,您说:

params.require(:user).permit(:productplan_ids => [])

但是你的参数是:

{
  ...,
  "user"=> {
    "productsku_ids"=>["", "4", "7"]
  }, 
  "commit"=>"Create User"
}

您允许 productplan_ids(应该是 product_plan_ids),但是在您的参数中有 productsku_ids(应该是 product_sku_ids)。

其他一些事情:

您应该通读 ruby style guide 以确保您的命名正确。

Class 名称应该是 CamelCase。所以,ProductPlan,而不是 Productplan

符号和变量应该是 SnakeCase。所以,:user_products,而不是 :userproducts.

如果控制器名称是面向资源的,则它们应该是复数,而不是单数。所以,ProductPlansController,而不是 ProductPlanController。 (我假设你有 ProductPlan 的所有常用 RESTful 操作,例如 newcreateeditupdate 等)

并且,现在 through: :user_products:through => :user_products 更传统。

所以:

class User < ActiveRecord::Base
  has_many :user_products
  has_many :product_plans, through: :user_products
end

class ProductPlan < ApplicationRecord
  has_many :user_products
  has_many :users, through: :user_products
end

class UserProduct < ApplicationRecord
  belongs_to :user
  belongs_to :product_plan
end

此外,您有一堆不匹配的 def ... end 语句:

class ProductPlanController < ApplicationController
  before_action :authenticate_user!

  def new 
      @user=User.new
    end  
  end # <= extra 'end' here

  def create
    @user = User.create(user_params)
    if @user.save
      render :action => 'index'
    else
      render :action =>'new'
    end
  # <= missing 'end' here

  private 

  def user_params
    params.require(:user).permit(:productplan_ids => [])
  end

end

我认为这是某种复制粘贴错误

我不知道你为什么这样做:

def create
  @user = User.create(user_params)
  if @user.save
    render :action => 'index'
  else
    render :action =>'new'
  end
end

在你的 ProductPlansController 中。是 ProductPlansController。它应该创建 ProductPlan,而不是 User