0
votes

following his tutorial, the home page from Static-Pages Controller renders a 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

Then, in the MicropostController.rb, an action for the partial micropost_form is declared:

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

Notice how, if micropost_form success, it gets redirected static_pages's index view, but, if failed, it renders static_pages home view (which also keeps the params in the form, so the user doesn't have to writype all the data), BUT, it needs to initialize static_pages's home controller instance variables (namely, feed_items).

Now, suppose StaticPages Controller's home has a long list of complex instances variables, how can MicropostController render (to keep form data upon failure) static_pages/home without creating that many instance variables?

note: this question is related to my previous one,but I wanted to understand this basic example before.

2
Don't use instance variables in partials - it greatly reduces the reusability of them, which is their main purpose. - sevenseacat

2 Answers

1
votes

how can MicropostController render (to keep form data upon failure) static_pages/home without creating that many instance variables?

The simple answer is that it can't. In Rails you cannot redirect internally - which is an intentional design. What that means you cannot "patch through" a request to StaticPagesController#home once the router has matched the request.

So in order for MicropostsController to render static_pages/home it needs to do the same job as StaticPagesController.

However if setting up the instance variables is arduous or you want to avoid repetition then a good technique is to use a module to extract the shared functionality.

# 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
0
votes

If your from refers to the instance variables, then you need to initialize the instance variables whenever you render the form, whether that's in the home method or the create method.

This is one of the reasons Sandi Metz came up with rule 4 of her Rules for Developers

Controllers can instantiate only one object. Therefore, views can only know about one instance variable and views should only send messages to that object

See here for all the rules... https://robots.thoughtbot.com/sandi-metz-rules-for-developers