表格中的字段从插入语句中丢失

时间:2014-08-31 17:08:25

标签: ruby-on-rails ruby-on-rails-4

尝试创建新行(产品)时,create方法生成的INSERT语句缺少声明为NOT NULL的product_type_id字段。我无法弄清楚为什么Rails不包含insert语句中的product_type_id字段。

尝试保存产品时出现以下错误。

Admin :: ProductsController #create中的ActiveRecord :: StatementInvalid

Mysql2 ::错误:字段'product_type_id'没有默认值:INSERT INTO productsbrand_idcreated_atdescription,{{1} },image_basemedia_embedmsrpnameprice_overridethumbnail_descupdated_atvendor_sku) VALUES(9,'2014-08-31 16:45:50','','a','b',33.0,'a',3.0,'','2014-08-31 16:45:50 ','',2015)

但是,products表有product_type_id字段:

year

,请求参数显示product_type_id及其值:

desc products
--------------

+-----------------+--------------+------+-----+---------+----------------+
| Field           | Type         | Null | Key | Default | Extra          |
+-----------------+--------------+------+-----+---------+----------------+
| id              | int(11)      | NO   | PRI | NULL    | auto_increment |
| product_type_id | int(11)      | NO   | MUL | NULL    |                |
| brand_id        | int(11)      | YES  | MUL | NULL    |                |
| name            | varchar(50)  | NO   |     | NULL    |                |
| thumbnail_desc  | varchar(200) | YES  |     | NULL    |                |
| description     | text         | NO   |     | NULL    |                |
| year            | int(11)      | YES  |     | NULL    |                |
| vendor_sku      | varchar(30)  | YES  | MUL | NULL    |                |
| msrp            | decimal(8,2) | YES  |     | NULL    |                |
| price_override  | decimal(8,2) | YES  |     | NULL    |                |
| visible         | tinyint(1)   | NO   |     | 1       |                |
| available       | tinyint(1)   | NO   |     | 1       |                |
| image_base      | varchar(255) | YES  |     | NULL    |                |
| video_source    | text         | YES  |     | NULL    |                |
| media_embed     | text         | YES  |     | NULL    |                |
| deleted_at      | datetime     | YES  |     | NULL    |                |
| created_at      | datetime     | YES  |     | NULL    |                |
| updated_at      | datetime     | YES  |     | NULL    |                |
+-----------------+--------------+------+-----+---------+----------------+
18 rows in set (0.01 sec)

产品型号:

Request

Parameters:

{"utf8"=>"✓",
 "authenticity_token"=>"VT42eeLLT/pyQ05ycfU/PeK92LIQ1P7NpWcPDOuOvsg=",
 "product"=>{"year"=>"2015",
 "brand_id"=>"9",
 "name"=>"a",
 "description"=>"",
 "thumbnail_desc"=>"",
 "category_ids"=>["",
 "29"],
 "product_class_ids"=>[""],
 "image_base"=>"a",
 "media_embed"=>"b",
 "vendor_sku"=>"",
 "msrp"=>"33",
 "price_override"=>"3",
 "visible"=>"1",
 "available"=>"1"},
 "commit"=>"Create Backpack",
 "product_type_id"=>"39"}

ProductType型号:

class Product < ActiveRecord::Base

  belongs_to :brand
  belongs_to :product_type

  has_and_belongs_to_many :categories
  has_and_belongs_to_many :product_classes

  scope :sorted, lambda { order("name ASC") }
  scope :notdeleted, lambda { where(:deleted_at => nil) }

  def active
    deleted_at.nil?
  end

end

:product_type_id符号在产品控制器的params.permit中声明:

class ProductType < ActiveRecord::Base

  has_many :product_classes
  has_many :products

  validates_presence_of :name

  scope :sorted, lambda { order("name ASC") }
  scope :notdeleted, lambda { where(:deleted_at => nil) }

  def active
     deleted_at.nil?
  end

  def active=(val)
     self.deleted_at = [nil, '', '0', false].member?(val) ? Time.now : nil
  end

end

new.html.erb

class Admin::ProductsController < ApplicationController

  layout 'admin'

  before_action :confirm_logged_in
  before_action :get_product, only: [:edit, :update, :delete, :destroy]
  before_action :get_stuff,   only: [:new, :create, :edit, :update, :delete, :destroy]

  def index
    @product_types = ProductType.notdeleted.sorted
  end

  def show
    #redirect_to(:action => 'manage_products')
  end

  def new
    @product_type = ProductType.find(params[:product_type_id])
    @product = Product.new({:product_type_id => @product_type.id})
  end

  def create
    @product = Product.new(product_params)
    if @product.save
      flash[:notice] = 'Product created.'
      redirect_to(:action => 'index', :product_type_id => @product_type.id)
    else
      render("new")
    end
  end

  def edit
  end

  def update
    if @product.update(product_params)
      flash[:notice] = 'Product updated.'
      redirect_to(:action => 'manage_products', :product_type_id => @product_type.id)
    else
      render("edit")
    end
  end

  def delete
  end

  def destroy
    @product.update(deleted_at: Time.now, visible: 0, available: 0)
    flash[:notice] = "Product deleted."
    redirect_to(:action => 'manage_products', :product_type_id => @product_type.id)
  end

  def manage_products
    id = params[:product_type_id]
    @product_type = ProductType.find(id)

    if params[:include_deleted] 
      @products = @product_type.products.sorted
    else
      @products = @product_type.products.notdeleted.sorted
    end

    #logger.debug("The size of products is #{@products.size}")
  end

  private

    def get_product
      @product = Product.find(params[:id])
      logger.debug("The product type id is #{@product.product_type_id}")
      @product_type = ProductType.find(@product.product_type_id)
      logger.debug("The product type is #{@product_type.name}")
      logger.debug("The product type has price is #{@product_type.has_price}")
    end

    def get_stuff
      @brands = Brand.sorted
      @categories = Category.sorted
    end

  def product_params
    params.require(:product).permit( :product_type_id, :brand_id, :name, :thumbnail_desc, :description, :year, :vendor_sku,
     :msrp, :price_override, :visible, :available, :image_base, :media_embed, :active, 
     :category_ids => [], :product_class_ids => [])
  end

end

最后,_form.html.erb

<% @page_title = "Create #{@product_type.name}" %>

<% content_for(:navigation) do -%>
    <p><a href="<%= admin_products_path %>"><img src="/assets/layout/icons/arrow_left.png" alt="Back" /> Back to <%= @product_type.name   %> List</a></p>
<% end -%>

<%= yield :navigation %>

  <%= form_for([:admin, @product], :url => {:action => 'create', :product_type_id => @product_type.id}) do |form| %>

  <%= render :partial => 'form', :locals => {:form => form} %>

  <div class="form-buttons">
    <%= submit_tag("Create #{@product_type.name}") %>
  </div>

  <% end %>

<%= yield :navigation %>

2 个答案:

答案 0 :(得分:0)

我认为你应该像这样重新订购product_type id:

"price_override"=>"3",
"visible"=>"1",
"available"=>"1",
"product_type_id"=>"39"},
"commit"=>"Create Backpack"

答案 1 :(得分:0)

要将缺少的字段放入insert语句,我必须在表单中包含该值并隐藏它:

  <% if @product.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@product.errors.count, "error") %> prohibited this page from being saved:</h2>
       <%= error_messages_for(@product) %>
    </div>
  <% end %>

<%= form.hidden_field :product_type_id, :value => @product_type.id %>

<table cellpadding="0" cellspacing="0" class="admintable">
   <tr> 
    <th>Year</th>
    <td><%= form.text_field :year, :size => 5 %></td>
  </tr>

我还将此行添加到create方法的开头:

    @product_type = ProductType.find(params[:product_type_id])

谢谢Alex,让我走上正轨。