Search code examples
ruby-on-railstwitterrescue

Rails | Rescue exception in model and use the error in controller


I am using the twitter gem to allow users to post tweets from my app.

This is my tweet.rb file

 class Tweet < ActiveRecord::Base
     belongs_to :user

     validates :user_id, :tweet, presence: true
     before_create :post_to_twitter

     def post_to_twitter
       begin
        user.twitter.update(tweet)
       rescue Twitter::Error => error
        // I want to do a redirect_to root_path, notice: "Please fix the error #{error.message}"
       // but its against MVC structure to pattern for a model to redirect, since its the task of a controller. How can I achieve this in controller
       end
     end
    end

In the rescue block of the post_to_twitter method, I want to do a redirect_to root_path, notice: "Please fix the error #{error.message}" but its against MVC structure to pattern for a model to redirect, since its the task of a controller. How can I achieve this in controller?

This is tweets_controller.rb file

class TweetsController < ApplicationController

      def new
        @tweet = Tweet.new
      end

      def create
        @tweet = Tweet.new(tweet_params)
        @tweet.user_id = current_user.id
        if @tweet.save
          redirect_to new_tweet_path, notice: "Your tweet has been successfully posted"
        else
          render 'new'
        end
      end

      private
      def tweet_params
        params.require(:tweet).permit(:tweet, :user_id)
      end

    end

Solution

  • You can add error to object when callback is not successful:

    def post_to_twitter
      begin
        user.twitter.update(tweet)
      rescue Twitter::Error => error
        # error will be appear in `@tweet.errors`
        errors.add(:base, "Please fix the error #{error.message}")
        false
      end
    end
    

    Then, do whatever you need in controller when @tweet.save returns false (and it will return false since the callback was not successful):

    def create
      @tweet = Tweet.new(tweet_params)
      @tweet.user_id = current_user.id
      if @tweet.save
        redirect_to new_tweet_path, notice: "Your tweet has been successfully posted"
      else
        # render 'new'
        redirect_to root_path, notice: @tweet.errors.full_messages.join(',')
      end
    end