当我尝试使用HABTM check_box_tag进行保存时,为什么会出现Unpermitted参数错误?

时间:2014-09-23 21:37:46

标签: ruby-on-rails ruby-on-rails-4 checkbox nested-forms has-and-belongs-to-many

Ruby版本:

ruby 2.1.2p95 (2014-05-08 revision 45877) [x86_64-linux]

Rails版本:

Rails 4.1.4

我在两个模型之间有一个HABTM关联:Product和Page。当我使用带有以下命令的控制台时,此关联很有效:

Product.first.pages << Page.first

我在我的products / _form.html.haml中插入了check_box_tag以显示我的网页。 check_box效果很好,我可以选中/取消选中我的所有页面。

问题是当我尝试提交表单时,我在复选框中所做的修改不会保存。我在两个方面都有这个问题。

我认为问题是我的日志中的未许可参数错误。

Started PATCH "/admin/pages/linge-de-lit" for 127.0.0.1 at 2014-09-23 23:13:40 +0200
Processing by Admin::PagesController#update as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"q/ZskL+Zijc8GMX9lF+EPgqc9uic9N9B/isWYHx7Cx0=", "page"=>{"category"=>"fabric", "title"=>"Linge de lit", "intro"=>"", "visibility"=>"1", "favorite"=>"0", "priority"=>"50", "product_ids"=>["", "1", "2"]}, "commit"=>"Save", "id"=>"linge-de-lit"}
  Page Load (0.3ms)  SELECT  "pages".* FROM "pages"  WHERE "pages"."slug" = 'linge-de-lit'  ORDER BY "pages"."id" ASC LIMIT 1
Unpermitted parameters: product_ids
   (0.3ms)  begin transaction
  Page Exists (0.3ms)  SELECT  1 AS one FROM "pages"  WHERE ("pages"."title" = 'Linge de lit' AND "pages"."id" != 5) LIMIT 1
   (0.2ms)  commit transaction
Redirected to http://localhost:3000/admin/pages/linge-de-lit
Completed 302 Found in 86ms (ActiveRecord: 1.1ms)

我认为问题是我强大的参数,但我不知道在哪里。

这是我的模特:

class Product < ActiveRecord::Base
  has_and_belongs_to_many :pages
end

class Page < ActiveRecord::Base
  has_and_belongs_to_many :products
  has_many :posts
  validates :category, presence: true
  validates :title, presence: true, length: {maximum: 20}, uniqueness: true

  extend FriendlyId
  friendly_id :title, :use => [:slugged, :finders]

  before_save :default_values
  def default_values
    self.title = self.title.capitalize
  end

#Scopes
  scope :visible, -> { where(visibility: true) }
  scope :favorite, -> { where(favorite: true) }

end

这是我的控制器:

class Admin::ProductsController < ApplicationController
  before_action :set_product, only: [:show, :edit, :update, :destroy]

  # GET /admin/products
  def index
    @products = Product.all
  end

  # GET /admin/products/1
  def show
  end

  # GET /admin/products/new
  def new
    @product = Product.new
    @pages = Page.all
  end

  # GET /admin/products/1/edit
  def edit
    @pages = Page.all
  end

  # POST /admin/products
  def create
    @product = Product.new(product_params)

    if @product.save
      redirect_to [:admin, @product], notice: 'Product was successfully created.'
    else
      render action: 'new'
    end
  end

  # PATCH/PUT /admin/products/1
  def update
    if @product.update(product_params)
      redirect_to [:admin, @product], notice: 'Product was successfully updated.'
    else
      render action: 'edit'
    end
  end

  # DELETE /admin/products/1
  def destroy
    @product.destroy
    redirect_to admin_products_url, notice: 'Product was successfully destroyed.'
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_product
      @product = Product.find(params[:id])
    end

    # Only allow a trusted parameter "white list" through.
    def product_params
      params.require(:product).permit(:name, :description, :brand_id, :price, :minimum_price, :shop_disponibility, :web_disponibility, :purchase_link, :favorite, {:pages_ids => []})
    end
end

class Admin::PagesController < ApplicationController
  before_action :set_page, only: [:show, :edit, :update, :destroy]

  # GET /admin/pages
  def index
    @pages = Page.all
  end

  # GET /admin/pages/1
  def show
  end

  # GET /admin/pages/new
  def new
    @page = Page.new
    @products = Product.all
  end

  # GET /admin/pages/1/edit
  def edit
    @products = Product.all
  end

  # POST /admin/pages
  def create
    @page = Page.new(page_params)

    if @page.save
      redirect_to [:admin, @page], notice: 'Page was successfully created.'
    else
      render action: 'new'
    end
  end

  # PATCH/PUT /admin/pages/1
  def update
    if @page.update(page_params)
      redirect_to [:admin, @page], notice: 'Page was successfully updated.'
    else
      render action: 'edit'
    end
  end

  # DELETE /admin/pages/1
  def destroy
    @page.destroy
    redirect_to admin_pages_url, notice: 'Page was successfully destroyed.'
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_page
      @page = Page.find(params[:id])
    end

    # Only allow a trusted parameter "white list" through.
    def page_params
      params.require(:page).permit(:category, :title, :intro, :visibility, :favorite, :priority, :products_ids => [])
    end
end

以下是我的观点:

# products/_form

= form_for([:admin, @product]) do |f|
  - if @product.errors.any?
    #error_explanation
      %h2= "#{pluralize(@product.errors.count, "error")} prohibited this product from being saved:"
      %ul
        - @product.errors.full_messages.each do |msg|
          %li= msg

  .field
    = f.label :name
    = f.text_field :name
  .field
    = f.label :description
    = f.text_area :description
  .field
    = f.label :brand_id
    = f.text_field :brand_id
  .field
    = f.label :price
    = f.text_field :price
  .field
    = f.label :minimum_price
    = f.check_box :minimum_price
  .field
    = f.label :shop_disponibility
    = f.check_box :shop_disponibility
  .field
    = f.label :web_disponibility
    = f.check_box :web_disponibility
  .field
    = f.label :purchase_link
    = f.text_field :purchase_link
  .field
    = f.label :favorite
    = f.check_box :favorite

  = hidden_field_tag "product[page_ids][]", nil
  - Page.all.each do |page|
    = check_box_tag "product[page_ids][]", page.id, @product.page_ids.include?(page.id), id: dom_id(page)
    = label_tag dom_id(page), page.title

  .actions
    = f.submit 'Save'

# pages/_form

= form_for([:admin, @page]) do |f|
  - if @page.errors.any?
    #error_explanation
      %h2= "#{pluralize(@page.errors.count, "error")} prohibited this page from being saved:"
      %ul
        - @page.errors.full_messages.each do |msg|
          %li= msg

  .field
    = f.label :category
    = f.select :category, options_for_select(@pages_categories), {:prompt => "- Sélectionner une catégorie -"}
  .field
    = f.label :title
    = f.text_field :title
  .field
    = f.label :intro
    = f.text_area :intro
  .field
    = f.label :visibility
    = f.check_box :visibility
  .field
    = f.label :favorite
    = f.check_box :favorite
  .field
    = f.label :priority
    = f.number_field :priority

  = hidden_field_tag "page[product_ids][]", nil
  - Product.all.each do |product|
    = check_box_tag "page[product_ids][]", product.id, @page.product_ids.include?(product.id), id: dom_id(product)
    = label_tag dom_id(product), product.name

  .actions
    = f.submit 'Save'

1 个答案:

答案 0 :(得分:3)

那里有一个拼写错误:)而不是

# Only allow a trusted parameter "white list" through.
def page_params
  params.require(:page).permit(:category, :title, :intro, :visibility, :favorite, :priority, :products_ids => [])
end

应该是product_ids:

# Only allow a trusted parameter "white list" through.
def page_params
  params.require(:page).permit(:category, :title, :intro, :visibility, :favorite, :priority, :product_ids => [])
end