All threads / Two Forms/Two Controllers/One Page: Passing Instance Variables, Routing, and Error Handling

Ask A Question

Notifications

You’re not receiving notifications from this thread.

Two Forms/Two Controllers/One Page: Passing Instance Variables, Routing, and Error Handling

Michael Becco asked in Rails

So... I'm having a higher level conceptual gap on how to deal with a scenario in which a form errs out on a page that has two forms relating to two different controllers.

My first knowledge gap to address is using instance variables in the else. Is there a more efficient or accepted means of populating the page after errors then making another hit to the DB?

The second knowledge gap to address is routing after an error. When I render timelines_index_path my routing becomes /alerts or /microposts and I understand what Rails is doing behind the scenes, I just am unclear what to actually do about that.

Here are my three controllers. Timelines list all micropost and alerts as well as the two forms for micropost and alerts .

class TimelinesController < ApplicationController
  layout 'timeline'
  before_action :authenticate_user!

  def index
    @microposts = Micropost.by_most_recent
    @micropost = Micropost.new
      @alert = Alert.new
    @alerts = Alert.all
  end
end

Alerts:

class AlertsController < ApplicationController

  def create
    @alert = current_user.alerts.build(alert_params)
    if @alert.save
      flash[:notice] = 'Alert Posted Successfully.'
      redirect_to timelines_index_path
    else
      @micropost = Micropost.new
      @microposts = Micropost.all
      @alerts = Alert.all
      render 'timelines/index', layout: 'timeline'
    end
  end

  private
    def alert_params
      params.require(:alert).permit(:symbol, :entry, :stop, :target, :shares, :comment)
    end
end

Micropost

class MicropostsController < ApplicationController
  before_action :authenticate_user!
  after_action :verify_authorized

  def create
    @micropost = current_user.microposts.build(micropost_params)
    authorize @micropost
    if @micropost.save
      flash[:notice] = 'Posted Successfully.'
      redirect_to timelines_index_path
    else
      @microposts = Micropost.all
      @alert = Alert.new
      @alerts = Alert.all
      render 'timelines/index', layout: 'timeline'
    end
  end

  def destroy
    @micropost = Micropost.find(params[:id])
    authorize @micropost
    @micropost.destroy
    redirect_to timelines_index_path, notice: 'Post Deleted.'
  end

  private
    def micropost_params
      params.require(:micropost).permit(:content)
    end
end

Hmm, you might want to consider doing AJAX submits of those forms so that they don't have to step on each others toes like that. This would also solve your very minor URL issue where submitting a form takes you back to the same page with a very differnet URL.

Have you considered submitting the forms with AJAX?

Evening Chris,

I will be using AJAX in the next refactor. The manner in which I itereated through my test for this project made me realize I didn't have a graceful fallback when JS is turned off. This lead to my controllers looking like a can of worms and hence my question.

Ultimately I'll put this in a respond_to block, I just wasn't sure if there is a way to stream line this.

Join the discussion

Want to stay up-to-date with Ruby on Rails?

Join 37,629+ developers who get early access to new tutorials, screencasts, articles, and more.

    We care about the protection of your data. Read our Privacy Policy.

    logo Created with Sketch.

    Ruby on Rails tutorials, guides, and screencasts for web developers learning Ruby, Rails, Javascript, Turbolinks, Stimulus.js, Vue.js, and more. Icons by Icons8

    © 2020 GoRails, LLC. All rights reserved.