我正在开发一个使用多对多关系的Rails应用程序,它需要连接表上的额外属性(除了两个相关实体的ID)。
在模型中,产品可以属于许多订单,订单可以包含许多产品。
所以我创建了一个操作,用于将产品分配给给定的订单,称为add_product_order
,并且在发送表单时处理表单的控制器方法为finish_add_product_order
:
def finish_add_product_order
@order = Order.find(params[:id])
@product = Product.find(params[:order][:products])
if @op = OrdersProduct.find_by_order_id_and_product_id(@order.id, @product.id)
@op.quantity = params['quantity'][0]
else
@op = OrdersProduct.new(:order => @order, :product => @product, :quantity => params['quantity'][0])
end
respond_to do |format|
if @op.save
format.html { redirect_to @order, notice: 'Order was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "add_product_order", notice: 'No se ha podido grabar.' }
format.json { render json: @order.errors, status: :unprocessable_entity }
end
end
end
orders_products表(用于存储相关的ID和数量)具有以下索引:
add_index :orders_products, [:order_id, :product_id], :unique => true
如果产品尚未在订单中(即正在调用OrdersProduct.new
),则上述操作(finish_add_product_order)可以正常工作。 但这是我已经存在的错误,我试图保存它:
SQLite3::SQLException: no such column: orders_products.: UPDATE "orders_products" SET "quantity" = 4 WHERE "orders_products"."" IS NULL
请求参数如下:以防万一:
{"utf8"=>"✓",
"_method"=>"put",
"authenticity_token"=>"TwPMk73MhCM2IeMfmf2g/fdm3+ahpyaxs1InULC/8ig=",
"order"=>{"products"=>"4"},
"quantity"=>["4"],
"commit"=>"Update Order",
"id"=>"2"}
我相信WHERE子句应该同时包含order和product id,以便识别受影响的行,但我不知道为什么列名不被包含,也不知道为什么它以“IS NULL”结尾。
有什么建议吗?感谢
修改
这是涉及的三个类的代码:
class Order < ActiveRecord::Base
belongs_to :user
has_many :gardens, :dependent => :destroy
has_many :products, :through => :orders_products
has_many :orders_products
attr_accessible :address, :delivery_date, :paid, :user, :orders_products_attributes
# hid some irrelevant methods
end
class Product < ActiveRecord::Base
has_many :gardens, :through => :gardens_products
has_many :gardens_products
has_many :orders, :through => :orders_products
has_many :orders_products
attr_accessible :cost, :description, :stock, :title, :x_size, :y_size, :pivot_x_position, :pivot_y_position, :is_gallery_product
validates_presence_of :cost, :stock, :title, :x_size, :y_size, :pivot_x_position, :pivot_y_position
validates_numericality_of :cost, :stock, :x_size, :y_size, :pivot_x_position, :pivot_y_position, :only_integer => true, :message => "Solo puede ser un numero entero"
validates_inclusion_of :cost, :in => 0..1000000, :message => "Solo puede estar entre 0 y 1 000 000"
validates_inclusion_of :stock, :in => 0..10000000, :message => "Solo puede estar entre 0 y 10 000 000"
validates_inclusion_of :x_size, :y_size, :in => 1..200, :message => "Solo puede estar entre 0 y 200"
# Poner el rango variable en los pivotes (dentro del rango del tamano)
validates_inclusion_of :pivot_x_position, :in => 1..200, :message => "El pivote debe estar dentro de las dimensiones del producto"
validates_inclusion_of :pivot_y_position, :in => 1..200, :message => "El pivote debe estar dentro de las dimensiones del producto"
validates :title, :length => { :minimum => 5},
:presence => { :message => "Debe tener un titulo de largo mayor que 5 caracteres" }
end
class OrdersProduct < ActiveRecord::Base
belongs_to :order, :dependent => :destroy
belongs_to :product
attr_accessible :order, :product, :quantity
validates_numericality_of :quantity,
:only_integer => true,
:message => "solo puede ser un numero entero"
validates_inclusion_of :quantity,
:in => 1..1000,
:message => "solo puede estar entre 1 y 1 000"
end
再次感谢
答案 0 :(得分:0)
使用“find_by_order_id_and_product_id
”调用替换此查找调用“where
”,并通过调用Relation
获取返回的first
对象的第一个对象。
if @op = OrdersProduct.where(:order_id => @order.id, :product_id => @product.id).first
@op.quantity = params['quantity'][0]
else
@op = OrdersProduct.new(:order => @order, :product => @product, :quantity => params['quantity'][0])
end
如果有帮助,请告诉我。
答案 1 :(得分:0)
由于orders_products表创建时没有id(使用create_table :orders_products, :id => :false do |t|...
),我所要做的就是为此添加一个id,并进行以下迁移:
class AddIdToOrdersProduct < ActiveRecord::Migration
def change
add_column :orders_products, :id, :primary_key
end
end
这样,它在执行rake db:migrate
之后起作用。