Michael Hartl Rails教程4,micropost部分和实例变量

时间:2016-08-19 12:26:29

标签: ruby-on-rails partial-views instance-variables railstutorial.org

在他的tutorial之后,Static-Pages Controller的主页呈现了partial_form:

<%= render 'shared/micropost_form' %> 

StaticPagesController.rb

def home
  @micropost  = current_user.microposts.build #for the form_form 
  @feed_items = current_user.feed.paginate(page: params[:page])
end

然后,在MicropostController.rb中,声明了部分micropost_form的操作:

class MicropostsController < ApplicationController
  def create
    @micropost = current_user.microposts.build(micropost_params)
    if @micropost.save
      flash[:success] = "Micropost created!"
      redirect_to root_url
    else
      @feed_items = []
      render 'static_pages/home'
    end
  end
end

请注意,如果micropost_form成功,它会重定向static_pages的索引视图,但是,如果失败,它会呈现static_pages主视图(这也会保留表单中的参数,因此用户不必将所有数据写入其中) ,但是,它需要初始化static_pages的主控制器实例变量(即feed_items)。

现在,假设StaticPages Controller的home有一长串复杂实例变量,MicropostController如何渲染(在失败时保存表单数据)static_pages / home而不创建那么多实例变量?

注意:此问题与my previous one有关,但我之前想要理解这个基本示例。

2 个答案:

答案 0 :(得分:1)

  

MicropostController如何呈现(在失败时保持表单数据)   static_pages / home没有创建那么多实例变量?

简单的答案是它不能。在Rails中,你无法在内部重定向 - 这是一种有意的设计。这意味着一旦路由器匹配请求,您就无法将请求“修补”到StaticPagesController#home

因此,为了让MicropostsController呈现static_pages/home,它需要执行与StaticPagesController相同的工作。

但是,如果设置实例变量很难或者你想避免重复,那么一个好的技术是使用模块来提取共享功能。

# app/controllers/concerns/feedable.rb
module Feedable
  protected

    def set_feed_items!
      @feed_items = FeedItem.includes(:comments).all
    end
end

class StaticPagesController < ActiveRecord::Base
  include Feedable

  # ...
  before_action :set_feed_items!, only: [:home]
end

class MicropostsController < ApplicationController
  include Feedable

  # ...
  def create
    @micropost = current_user.microposts.build(micropost_params)
    if @micropost.save
      flash[:success] = "Micropost created!"
      redirect_to root_url
    else
      set_feed_items!
      render 'static_pages/home'
    end
  end
end

答案 1 :(得分:0)

如果你的from引用了实例变量,那么无论是在home方法还是create方法中,你都需要在渲染表单时初始化实例变量。

这是Sandi Metz提出的“开发者规则”第4条的原因之一

  

控制器只能实例化一个对象。因此,视图只能   知道一个实例变量,视图应该只发送消息   到那个对象

请参阅此处查看所有规则...... https://robots.thoughtbot.com/sandi-metz-rules-for-developers