diff --git a/app/assets/javascripts/discourse/components/screen_track.js b/app/assets/javascripts/discourse/components/screen_track.js index 34b2f03facf..ab15f7dde9b 100644 --- a/app/assets/javascripts/discourse/components/screen_track.js +++ b/app/assets/javascripts/discourse/components/screen_track.js @@ -98,7 +98,7 @@ Discourse.ScreenTrack = Ember.Object.extend({ highestSeen = Math.max(highestSeen, parseInt(postNumber, 10)); }); - var highestSeenByTopic = Discourse.Session.current('highestSeenByTopic'); + var highestSeenByTopic = Discourse.Session.currentProp('highestSeenByTopic'); if ((highestSeenByTopic[topicId] || 0) < highestSeen) { highestSeenByTopic[topicId] = highestSeen; Discourse.TopicTrackingState.current().updateSeen(topicId, highestSeen); diff --git a/app/assets/javascripts/discourse/mixins/singleton.js b/app/assets/javascripts/discourse/mixins/singleton.js new file mode 100644 index 00000000000..0a69684a3c7 --- /dev/null +++ b/app/assets/javascripts/discourse/mixins/singleton.js @@ -0,0 +1,45 @@ +/** + This mixin allows a class to return a singleton, as well as a method to quickly + read/write attributes on the singleton. + + @class Discourse.Singleton + @extends Ember.Mixin + @namespace Discourse + @module Discourse +**/ +Discourse.Singleton = Em.Mixin.create({ + + /** + Returns the current singleton instance of the class. + + @method current + @returns {Ember.Object} the instance of the singleton + **/ + current: function() { + if (!this._current) { + this._current = this.create({}); + } + + return this._current; + }, + + /** + Returns or sets a property on the singleton instance. + + @method currentProp + @param {String} property the property we want to get or set + @param {String} value the optional value to set the property to + @returns the value of the property + **/ + currentProp: function(property, value) { + if (typeof(value) !== "undefined") { + this.current().set(property, value); + return value; + } else { + return this.current().get(property); + } + } + +}); + + diff --git a/app/assets/javascripts/discourse/models/session.js b/app/assets/javascripts/discourse/models/session.js index 0025ba5b617..52a44444d7c 100644 --- a/app/assets/javascripts/discourse/models/session.js +++ b/app/assets/javascripts/discourse/models/session.js @@ -1,6 +1,6 @@ /** A data model representing current session data. You can put transient - data here you might want later. + data here you might want later. It is not stored or serialized anywhere. @class Session @extends Discourse.Model @@ -13,28 +13,4 @@ Discourse.Session = Discourse.Model.extend({ } }); -Discourse.Session.reopenClass({ - - /** - Returns the current session. - - @method current - @returns {Discourse.Session} the current session singleton - **/ - current: function(property, value) { - if (!this.currentSession) { - this.currentSession = Discourse.Session.create(); - } - - // If we found the current session - if (typeof property !== "undefined") { - if (typeof value !== "undefined") { - this.currentSession.set(property, value); - } else { - return this.currentSession.get(property); - } - } - - return property ? this.currentSession.get(property) : this.currentSession; - } -}); +Discourse.Session.reopenClass(Discourse.Singleton); diff --git a/app/assets/javascripts/discourse/models/topic.js b/app/assets/javascripts/discourse/models/topic.js index 4d46d1eaca8..dc49503529a 100644 --- a/app/assets/javascripts/discourse/models/topic.js +++ b/app/assets/javascripts/discourse/models/topic.js @@ -87,7 +87,7 @@ Discourse.Topic = Discourse.Model.extend({ // So take what the browser has seen into consideration. displayNewPosts: function() { var delta, highestSeen, result; - if (highestSeen = Discourse.Session.current('highestSeenByTopic')[this.get('id')]) { + if (highestSeen = Discourse.Session.currentProp('highestSeenByTopic')[this.get('id')]) { delta = highestSeen - this.get('last_read_post_number'); if (delta > 0) { result = this.get('new_posts') - delta; diff --git a/app/assets/javascripts/discourse/models/topic_list.js b/app/assets/javascripts/discourse/models/topic_list.js index 0155bd536b5..cbc83606b6f 100644 --- a/app/assets/javascripts/discourse/models/topic_list.js +++ b/app/assets/javascripts/discourse/models/topic_list.js @@ -45,7 +45,7 @@ Discourse.TopicList = Discourse.Model.extend({ }); topicList.set('more_topics_url', result.topic_list.more_topics_url); - Discourse.Session.current('topicList', topicList); + Discourse.Session.currentProp('topicList', topicList); topicList.set('loadingMore', false); return result.topic_list.more_topics_url; @@ -75,7 +75,7 @@ Discourse.TopicList = Discourse.Model.extend({ t.set('highlight', true); topics.insertAt(0,t); }); - Discourse.Session.current('topicList', topicList); + Discourse.Session.currentProp('topicList', topicList); }); } }); diff --git a/app/assets/javascripts/discourse/routes/filtered_list_route.js b/app/assets/javascripts/discourse/routes/filtered_list_route.js index 1f7b5703a06..fb6a6f2e159 100644 --- a/app/assets/javascripts/discourse/routes/filtered_list_route.js +++ b/app/assets/javascripts/discourse/routes/filtered_list_route.js @@ -41,7 +41,7 @@ Discourse.FilteredListRoute = Discourse.Route.extend({ listController.set('canCreateTopic', topicList.get('can_create_topic')); listTopicsController.set('model', topicList); - var scrollPos = Discourse.Session.current('topicListScrollPosition'); + var scrollPos = Discourse.Session.currentProp('topicListScrollPosition'); if (scrollPos) { Em.run.next(function() { $('html, body').scrollTop(scrollPos); diff --git a/app/assets/javascripts/discourse/routes/topic_route.js b/app/assets/javascripts/discourse/routes/topic_route.js index 40e4a19907c..04e752e2d0e 100644 --- a/app/assets/javascripts/discourse/routes/topic_route.js +++ b/app/assets/javascripts/discourse/routes/topic_route.js @@ -71,7 +71,7 @@ Discourse.TopicRoute = Discourse.Route.extend({ this._super(); var topic = this.modelFor('topic'); - Discourse.Session.current('lastTopicIdViewed', parseInt(topic.get('id'), 10)); + Discourse.Session.currentProp('lastTopicIdViewed', parseInt(topic.get('id'), 10)); this.controllerFor('search').set('searchContext', topic.get('searchContext')); }, diff --git a/app/mailers/user_notifications.rb b/app/mailers/user_notifications.rb index 177f9ade8d9..f99df4359e2 100644 --- a/app/mailers/user_notifications.rb +++ b/app/mailers/user_notifications.rb @@ -100,7 +100,6 @@ class UserNotifications < ActionMailer::Base end def notification_email(user, opts) - return unless @notification = opts[:notification] return unless @post = opts[:post] diff --git a/test/javascripts/mixins/singleton_test.js b/test/javascripts/mixins/singleton_test.js new file mode 100644 index 00000000000..95216983227 --- /dev/null +++ b/test/javascripts/mixins/singleton_test.js @@ -0,0 +1,37 @@ +module("Discourse.Singleton"); + +test("current", function() { + var DummyModel = Ember.Object.extend({}); + DummyModel.reopenClass(Discourse.Singleton); + + var current = DummyModel.current(); + present(current, 'current returns the current instance'); + equal(current, DummyModel.current(), 'calling it again returns the same instance'); + notEqual(current, DummyModel.create({}), 'we can create other instances that are not the same as current'); +}); + +test("currentProp reading", function() { + var DummyModel = Ember.Object.extend({}); + DummyModel.reopenClass(Discourse.Singleton); + var current = DummyModel.current(); + + blank(DummyModel.currentProp('evil'), 'by default attributes are blank'); + current.set('evil', 'trout'); + equal(DummyModel.currentProp('evil'), 'trout', 'after changing the instance, the value is set'); +}); + +test("currentProp writing", function() { + var DummyModel = Ember.Object.extend({}); + DummyModel.reopenClass(Discourse.Singleton); + + blank(DummyModel.currentProp('adventure'), 'by default attributes are blank'); + var result = DummyModel.currentProp('adventure', 'time'); + equal(result, 'time', 'it returns the new value'); + equal(DummyModel.currentProp('adventure'), 'time', 'after calling currentProp the value is set'); + + DummyModel.currentProp('count', 0); + equal(DummyModel.currentProp('count'), 0, 'we can set the value to 0'); + + DummyModel.currentProp('adventure', null); + equal(DummyModel.currentProp('adventure'), null, 'we can set the value to null'); +}); \ No newline at end of file diff --git a/test/javascripts/models/session_test.js b/test/javascripts/models/session_test.js index 612ad6f40eb..ce33a58428e 100644 --- a/test/javascripts/models/session_test.js +++ b/test/javascripts/models/session_test.js @@ -1,25 +1,6 @@ module("Discourse.Session"); -test('current', function(){ - var session = Discourse.Session.current(); - - present(session, "We have a current site session"); - equal(session, Discourse.Session.current(), "Calling it a second time returns the same instance"); - - blank(Discourse.Session.current('orange'), "by default properties are nil"); - session.set('orange', 'newBlack'); - equal(Discourse.Session.current('orange'), "newBlack", "it remembers values"); - - Discourse.Session.current('orange', 'juice'); - equal(session.get('orange'), "juice", "it can be updated"); - - Discourse.Session.current('zero', 0); - equal(session.get('zero'), 0); -}); - test('highestSeenByTopic', function() { - var session = Discourse.Session.current(); deepEqual(session.get('highestSeenByTopic'), {}, "by default it returns an empty object"); - }); \ No newline at end of file