В Rails 5 многошаговой форме с использованием Wicked Gem появляется ошибка Forbidden Method

Попытка выяснить, как получить многошаговую форму для объекта, который пользователь будет строить с использованием драгоценного камня Wicked Wizard. Я следил за документами на github самоцвета, и на этот вопрос сам Шим ответил, но на последнем шаге мастера я получаю сообщение об ошибке запрещенного метода, и пытаюсь его отправить. Я видел в других вопросах, чтобы ссылаться на сильные параметры, и я также использовал это, и я не уверен, что является причиной ошибки. Пока у меня есть следующее.

Сообщение об ошибке:

ActiveModel::ForbiddenAttributesError (ActiveModel::ForbiddenAttributesError):

app/controllers/places/steps_controller.rb:14:in `update'
Started GET "/places/20/steps/id" for 127.0.0.1 at 2017-07-02 03:10:57 -0400
Processing by Places::StepsController#show as HTML
  Parameters: {"place_id"=>"20", "id"=>"id"}
  Place Load (183.0ms)  SELECT  "places".* FROM "places" WHERE "places"."id" = ? LIMIT ?  [["id", 20], ["LIMIT", 1]]
  Rendering places/steps/id.html.erb within layouts/application
  Rendered places/steps/id.html.erb within layouts/application (851.5ms)
Completed 200 OK in 5753ms (Views: 4688.2ms | ActiveRecord: 183.0ms)


Started PUT "/places/20/steps/id" for 127.0.0.1 at 2017-07-02 03:11:24 -0400
Processing by Places::StepsController#update as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"/VrDWevWLY+A6841zIR5awBGopfnoXWxE8zf+6xkogJC6ufPQ+qYGp4Mg72N3Dlc547oSF/cXa4c/vMK+JU6qg==", "place"=>{"cost"=>"$100.00", "user_id"=>"1"}, "commit"=>"Complete", "place_id"=>"20", "id"=>"id"}
  Place Load (14.9ms)  SELECT  "places".* FROM "places" WHERE "places"."id" = ? LIMIT ?  [["id", 20], ["LIMIT", 1]]
   (34.9ms)  begin transaction
   (0.1ms)  rollback transaction
Completed 500 Internal Server Error in 212ms (ActiveRecord: 49.8ms)



ActiveModel::ForbiddenAttributesError (ActiveModel::ForbiddenAttributesError):

app/controllers/places/steps_controller.rb:14:in `update'

schema.rb

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

  create_table "places", force: :cascade do |t|
    t.string "name"
    t.string "location"
    t.string "cost"
    t.date "available"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.integer "user_id"
    t.string "status"
    t.index ["user_id"], name: "index_places_on_user_id"
  end

  create_table "users", force: :cascade do |t|
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.string "username"
    t.string "password_digest"
  end

end

place.rb

class Place < ApplicationRecord
    belongs_to :user

    validates :name, :location, :cost, :available, :presence => true, :if => :active?

  def active?
    status == 'active'      
  end

end

places_controller.rb

class PlacesController < ApplicationController
  before_action :set_place, only: [:show, :edit, :update, :destroy]

  # GET /places
  # GET /places.json
  def index
    @places = Place.where.not(name: nil)
  end

  # GET /places/1
  # GET /places/1.json
  def show
  end

  # GET /places/new
  def new
    @place = Place.new
  end

  # GET /places/1/edit
  def edit
  end

  # POST /places
  # POST /places.json
  def create
    @place = Place.new
    if @place.save(validate: false)
      redirect_to place_step_path(place_id: @place.id, id: :date)
    else
      render new
    end
  end

  # PATCH/PUT /places/1
  # PATCH/PUT /places/1.json
  def update
    respond_to do |format|
      if @place.update(place_params)
        format.html { redirect_to @place, notice: 'Place was successfully updated.' }
        format.json { render :show, status: :ok, location: @place }
      else
        format.html { render :edit }
        format.json { render json: @place.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /places/1
  # DELETE /places/1.json
  def destroy
    @place.destroy
    respond_to do |format|
      format.html { redirect_to places_url, notice: 'Place was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

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

    # Never trust parameters from the scary internet, only allow the white list through.
    def place_params
      params.require(:place).permit(:name, :location, :cost, :available, :user_id, :status)
    end
end

steps_controller.rb

class Places::StepsController < ApplicationController
  include Wicked::Wizard

  steps :date, :id

  def show
    @place = Place.find(params[:place_id])
    render_wizard
  end

  def update
    @place = Place.find(params[:place_id])
    params[:place][:status] = 'active' if step == steps.last
    @place.update_attributes(params[:place])
    render_wizard @place
  end

  def create
    @place = Place.create
    redirect_to wizard_path(steps.first, :place_id => @product.id)

  end


private

end

routes.rb

Rails.application.routes.draw do

  root 'static_pages#home'
  resources :places
  resources :places do
    resources :steps, controller: 'places/steps'
  end


  resources :users



  # session routes
  resources :sessions
  get 'session/new'
  get '/sessions/new', to: 'sessions#new'
  post '/sessions/new', to: 'sessions#create'
  get '/logout', to: 'sessions#destroy'
  delete '/logout', to: 'sessions#destroy'

end

date.html.erb

<%= form_for @place, method: :put, url: wizard_path do |f| %>
  <% if f.object.errors.any? %>
    <div class="error-messages">
        <% f.object.errors.full_messages.each do |error| %>
          <p><%= error %></p>
          <% end %>
    </div>
  <% end %>
  <div class="h2">When Is Place available?</div>
  <div class="fied">
    <%= f.label "Date" %>
    <%= f.date_select :available, start_year: 2017 %>
  </div>
  <div class="actions">
    <%= f.submit "Next" %>
    or <%= link_to "skip this step", next_wizard_path %>
  </div>
<% end %>

id.html.erb

<%= form_for @place, method: :put, url: wizard_path do |f| %>
  <% if f.object.errors.any? %>
    <div class="error-messages">
      <% f.object.errors.full_messages.each do |error| %>
        <p><%= error %></p>
      <% end %>
    </div>
  <% end %>
  <div class="h2">
    <div class="field">
      <%= f.label "Cost" %>
      <%= f.text_field :cost %>
    </div>
    <div class="field">
      <%= f.label "Belongs to" %>
      <%= f.text_field :user_id %>
    </div>
  </div>

  <div class="actions">
    <%= f.submit "Complete" %>
  </div>
<% end %>

1 ответ

Решение

ActiveModel::ForbiddenAttributesError (ActiveModel::ForbiddenAttributesError)

Я верю update метод в Places::StepsController виновник Вы не используете strong params в этом методе. Попробуйте изменить это ниже

def update
  @place = Place.find(params[:place_id])
  params[:place][:status] = 'active' if step == steps.last
  @place.update_attributes(place_params) #here you should use strong params
  render_wizard @place
end

И определить place_params под private

private
def place_params
  params.require(:place).permit(:name, :location, :cost, :available, :user_id, :status)
end
Другие вопросы по тегам