diff --git a/app/assets/javascripts/discourse/controllers/topic_controller.js b/app/assets/javascripts/discourse/controllers/topic_controller.js index 8c12943ee6e..a1f4812ebbe 100644 --- a/app/assets/javascripts/discourse/controllers/topic_controller.js +++ b/app/assets/javascripts/discourse/controllers/topic_controller.js @@ -223,6 +223,8 @@ Discourse.TopicController = Discourse.ObjectController.extend(Discourse.Selected this.set('loadingExpanded', true); post.expand().then(function() { self.set('firstPostExpanded', true); + }).catch(function(error) { + bootbox.alert($.parseJSON(error.responseText).errors); }).finally(function() { self.set('loadingExpanded', false); }); diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 2690c25bf52..ce55c6060e4 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -5,10 +5,12 @@ require_dependency 'custom_renderer' require_dependency 'archetype' require_dependency 'rate_limiter' require_dependency 'crawler_detection' +require_dependency 'json_error' class ApplicationController < ActionController::Base include CurrentUser include CanonicalURL::ControllerExtensions + include JsonError serialization_scope :guardian @@ -242,11 +244,7 @@ class ApplicationController < ActionController::Base end def render_json_error(obj) - if obj.present? - render json: MultiJson.dump(errors: obj.errors.full_messages), status: 422 - else - render json: MultiJson.dump(errors: [I18n.t('js.generic_error')]), status: 422 - end + render json: MultiJson.dump(create_errors_json(obj)), status: 422 end def success_json diff --git a/app/controllers/posts_controller.rb b/app/controllers/posts_controller.rb index ed787622e1d..c313de95d3f 100644 --- a/app/controllers/posts_controller.rb +++ b/app/controllers/posts_controller.rb @@ -151,6 +151,8 @@ class PostsController < ApplicationController doc.content end render json: {cooked: content} + rescue + render_json_error I18n.t('errors.embed.load_from_remote') end def recover diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml index 75165bc199d..58599caf0e3 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -28,6 +28,10 @@ en: via: "%{username} via %{site_name}" is_reserved: "is reserved" + errors: + embed: + load_from_remote: "There was an error loading that post." + backup: operation_already_running: "An operation is currently running. Can't start a new job right now." backup_file_should_be_tar_gz: "The backup file should be a .tar.gz archive." diff --git a/lib/json_error.rb b/lib/json_error.rb new file mode 100644 index 00000000000..d155a1ddd3a --- /dev/null +++ b/lib/json_error.rb @@ -0,0 +1,21 @@ +module JsonError + + def create_errors_json(obj) + + # If we're passed a string, assume that is the error message + return {errors: [obj]} if obj.is_a?(String) + + # If it looks like an activerecord object, extract its messages + return {errors: obj.errors.full_messages } if obj.respond_to?(:errors) && obj.errors.present? + + # default to a generic error + JsonError.generic_error + end + + private + + def self.generic_error + {errors: [I18n.t('js.generic_error')]} + end + +end diff --git a/spec/components/json_error_spec.rb b/spec/components/json_error_spec.rb new file mode 100644 index 00000000000..a95d284e3d9 --- /dev/null +++ b/spec/components/json_error_spec.rb @@ -0,0 +1,55 @@ +require 'spec_helper' +require_dependency 'json_error' + +shared_examples "a generic error" do + let(:result) { creator.create_errors_json(obj) } + + it "should have a result object" do + result.should be_present + end + + it "has a generic error message" do + result[:errors].should == [I18n.t('js.generic_error')] + end +end + +describe JsonError do + + let(:creator) { Object.new.extend(JsonError) } + + describe "with a nil argument" do + it_behaves_like "a generic error" do + let(:obj) { nil } + end + end + + describe "with an empty array" do + it_behaves_like "a generic error" do + let(:obj) { [] } + end + end + + describe "with an activerecord object with no errors" do + it_behaves_like "a generic error" do + let(:obj) { Fabricate.build(:user) } + end + end + + describe "with a string" do + it "returns the string in the error format" do + creator.create_errors_json("test error").should == {errors: ["test error"]} + end + end + + describe "an activerecord objec with errors" do + let(:invalid_user) { User.new } + it "returns the errors correctly" do + invalid_user.should_not be_valid + result = creator.create_errors_json(invalid_user) + result.should be_present + result[:errors].should_not be_blank + end + end + +end +