2017-07-02 84 views
0

一直想弄清楚如何獲取用戶使用Wicked Wizard gem構建的對象的多步表單。我一直在關注gem的github上的文檔,並且這個Scheem的回答是自己的,但是在嚮導的最後一步並且正在嘗試提交時,我遇到了禁止的方法錯誤。我在其他問題中看到了strong parameters,我也一直在使用它,並且不確定是什麼導致了錯誤。到目前爲止,我有以下幾點。Rails 5使用Wicked Gem的多步表單變得越來越糟糕方法錯誤

錯誤消息:

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

AC tiveModel :: ForbiddenAttributesError (::加載ActiveModel ForbiddenAttributesError)

我相信Places::StepsControllerupdate方法是罪魁禍首。你是在該方法中不使用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_paramsprivate

private 
def place_params 
    params.require(:place).permit(:name, :location, :cost, :available, :user_id, :status) 
end 
+0

謝謝你的迴應,我很欣賞的快速反應,所以我已經停止得到一個forbiddenmethod誤差,取而代之的則是說我「用戶必須存在」,或者如果我跳過它說其他字段不能爲空的步驟。任何想法? –

+0

@LuisMejia如果您使用的是Rails 5,請嘗試設置'optional:true' in Place model'belongs_to:user,optional:true' – Pavan

+0

再次感謝,清除了User必須存在,但其他字段都說「不可以」空白「,他們正在填補,並列在參數 –