首页 > 解决方案 > 如何在不同的控制器视图上呈现 Rails 多步表单(向导)的第一步?

问题描述

我一直在关注 Railscast 第 217 集(http://railscasts.com/episodes/217-multistep-forms?view=asciicast),效果很好。对于我的应用程序,我真的希望在我的主页上呈现表单的第一步,这是我真正陷入困境的地方。

每当我尝试渲染第一步部分时,我都会遇到某种错误,即使在玩弄代码之后也是如此。到目前为止,我已经尝试过:

通过这些修复,我不断收到错误消息:

undefined local variable or method `f'

更新

我添加<%=form_for(@zerch) do |f| %>到部分的顶部,它实际上使渲染工作,但是我遇到的下一个问题是单击时'Continue'我会收到错误:

undefined method `deep_merge!' for nil:NilClass

从我的create操作中的这行代码:

session[:zerch_params].deep_merge!(params.permit![:zerch]) if params[:zerch]

但这里真的很有趣:如果我从部分来源home_index的原始new视图路由到_location_step,我可以浏览整个表单并提交它并且它可以工作。但是如果我从主页索引开始,它就不起作用。但是,我不确定为什么。


这是我的代码:

家庭控制器

class HomeController < ApplicationController
  def index
    @zerch = Zerch.new(session[:zerch_params])
  end
end

home_index

<%= render 'zerches/location_step' %> #I tried f: f here and it didn't work

zerches_controller

类 ZerchesController < InheritedResources::Base

def index
    @zerches = Zerch.all
end

def show
    @zerch = Zerch.find(params[:id])
end

def new
    session[:zerch_params] ||= {}
    @zerch = Zerch.new(session[:zerch_params])
    @zerch.current_step = session[:zerch_step]
end

def create
    session[:zerch_params].deep_merge!(params.permit![:zerch]) if params[:zerch]
    @zerch = Zerch.new(session[:zerch_params])
    @zerch.current_step = session[:zerch_step]
    if @zerch.valid?
        if params[:back_button]
            @zerch.previous_step
        elsif @zerch.last_step?
            @zerch.save if @zerch.all_valid?
        else            
            @zerch.next_step
        end
        session[:zerch_step] = @zerch.current_step
end
if @zerch.new_record?
    render "new"
else
    session[:zerch_step] = session[:zerch_params] = nil
    flash[:notice] = "zerch complete!"
    redirect_to @zerch
end
end


private

def zerch_params
  params.require(:zerch).permit(:location, :category, :price)
end

end

泽奇模型

class Zerch < ApplicationRecord
    attr_writer :current_step

    validates_presence_of :location, :if => lambda { |o| o.current_step == "location" }
    validates_presence_of :category, :if => lambda { |o| o.current_step == "category" }
    validates_presence_of :price, :if => lambda { |o| o.current_step == "price" }

    def current_step
        @current_step || steps.first
    end

    def steps
        %w[location category price]
    end

    def next_step
        self.current_step = steps[steps.index(current_step)+1]
    end

    def previous_step
        self.current_step = steps[steps.index(current_step)-1]
    end

    def first_step?
        current_step == steps.first
    end

    def last_step?
        current_step == steps.last
    end

    def all_valid?
        steps.all? do |step|
            self.current_step = step
            valid?
        end
    end
end

新的.html.erb

<%= form_for(@zerch) do |f| %>
  <%#= f.error_messages %>
  <%#= f.error_notification message: f.object.errors[:base].to_sentence if f.object.errors[:base].present? %>

 <%= render "#{@zerch.current_step}_step", f: f %>

  <div class="form-actions">
    <%= f.submit "Continue" %>
    <%= f.submit "Back", :name => "back_button" unless @zerch.first_step? %>
  </div>
<% end %>


<%= link_to "Home", root_path %

第一步部分

<%= f.label :location %>
<%= f.text_field :location %>
<div class="form-actions">
    <%= f.submit "Continue" %>
    <%= f.submit "Back", :name => "back_button" unless @zerch.first_step? %>
</div>

标签: ruby-on-railsformswizard

解决方案


推荐阅读