Rails 5 有很多通过实现

Posted

技术标签:

【中文标题】Rails 5 有很多通过实现【英文标题】:Rails 5 have many through implementation 【发布时间】:2017-06-30 09:59:08 【问题描述】:

我是 Rails 新手。尝试就位在我的应用程序中有很多通过关联,因为用户将能够通过订单制作股票。目前,我收到错误“表单中的第一个参数不能包含 nil 或为空”。

这是我的代码

Schema.rb

ActiveRecord::Schema.define(version: 20170630092012) do

  create_table "admins", force: :cascade do |t|
    t.string "email", default: "", null: false
    t.string "encrypted_password", default: "", null: false
    t.string "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.integer "sign_in_count", default: 0, null: false
    t.datetime "current_sign_in_at"
    t.datetime "last_sign_in_at"
    t.string "current_sign_in_ip"
    t.string "last_sign_in_ip"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["email"], name: "index_admins_on_email", unique: true
    t.index ["reset_password_token"], name: "index_admins_on_reset_password_token", unique: true
  end

  create_table "orders", force: :cascade do |t|
    t.boolean "agreement"
    t.integer "user_id"
    t.integer "stock_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["stock_id"], name: "index_orders_on_stock_id"
    t.index ["user_id"], name: "index_orders_on_user_id"
  end

# Could not dump table "stocks" because of following StandardError
#   Unknown type 'fixnum' for column 'product_code'

  create_table "users", force: :cascade do |t|
    t.string "email", default: "", null: false
    t.string "encrypted_password", default: "", null: false
    t.string "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.integer "sign_in_count", default: 0, null: false
    t.datetime "current_sign_in_at"
    t.datetime "last_sign_in_at"
    t.string "current_sign_in_ip"
    t.string "last_sign_in_ip"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["email"], name: "index_users_on_email", unique: true
    t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
  end

end

app/models/user.rb

class User < ApplicationRecord
  has_many :orders
  has_many :stocks, through: :orders
end

app/models/stock.rb

class Stock < ApplicationRecord
  has_many :orders
  has_many :users, through: :orders
end

app/models/order.rb

class Order < ApplicationRecord
  belongs_to :user
  belongs_to :stock
end

app/controllers/orders_controller.rb

class OrdersController < ApplicationController
  # before_action :authenticate_user!, :only => [:history]

  def history
    @orders = current_user.orders.order('created_at DESC')
  end

  def new
    @stock= Stock.new
    @order = @stock.orders.build
    @user = @orders.build_user
  end

  def create
    User.new(user_params)
  end

private

  def user_params
     params.require(:user).permit(:id, :agreement, :user_id, :stock_id [:id, physician_attributes: [:id ] )
  end
end

app/controllers/stocks_controller.rb

class StocksController < ApplicationController
  before_action :authenticate_admin!, :except => [:index, :show]

  def index
    @items = Stock.all.order('created_at DESC')
  end

  def new
    @item = current_admin.stocks.new
  end

  def create
    @item = current_admin.stocks.new(stock_params)
    if @item.save
       flash[:notice] = "A #@item.name has been listed."
       redirect_to root_path
    else
      flash[:alart] = "Error: Make sure that you submitting valid information"
    end
  end

  def update
    @item = Stock.find(params[:id])
    if @item.update
      flash[:notice] = "#@item.name has been updated."
      render @item
    else
      render 'edit'
    end
  end

  def show
    find_item
  end

  def edit
    find_item
  end

  def destroy
    find_item
    if @item.destroy
      redirect_to root_path
      flash[:notice] = "#@item.name has been deleted."
    else
      flash[:alert] = "#@item.name could not be deleted."
    end
  end

  private

  def find_item
    @item = Stock.find(params[:id])
  end

  def stock_params
    params.fetch(:stock).permit(:name, :description, :image, :fixed)
  end
end


views/stocks/_agreement_form.html.erb

<% form_for(@orders) do |order_form| %>
  <p>
    <%= order_form.label :agree %>
    <%= order_form.checkbox :agree %>
    <%= order_form.submit 'Create' %>
  </p>
<% end %>

提前致谢,

【问题讨论】:

你在哪个文件中渲染_agreement_form.html.erb partial? @Pavan 来自stocks/show.html.erb 发布您的stocks_controller 【参考方案1】:
def show
  find_item
  @order = @item.orders.build
end

我认为你应该更新&lt;% form_for(@orders) do |order_form| %&gt; 它应该使用@order

【讨论】:

并且find_item 应该在行动之前而不是在行动中调用它。

以上是关于Rails 5 有很多通过实现的主要内容,如果未能解决你的问题,请参考以下文章

Rails 有很多通过有一个多态

如何在rails中有很多通过创建关系

Rails 4 ActiveRecord 有很多通过关系不能从 sql 文件读取

Rails has_many,如何实现嵌套关联?

Rails API:实现身份验证的最佳方式?

Rails 上的两个作用域有很多通过返回比一个单一作用域更大的计数