|
| 1 | +originalPublish = Meteor.publish |
| 2 | + |
| 3 | +Meteor.publish = (name, publishFunction) -> |
| 4 | + originalPublish name, (args...) -> |
| 5 | + publish = @ |
| 6 | + |
| 7 | + relatedPublish = null |
| 8 | + ready = false |
| 9 | + |
| 10 | + publishDocuments = -> |
| 11 | + oldRelatedPublish = relatedPublish |
| 12 | + |
| 13 | + Tracker.nonreactive => |
| 14 | + relatedPublish = publish._recreate() |
| 15 | + |
| 16 | + # We copy overridden methods if they exist |
| 17 | + for own key, value of publish when key in ['added', 'changed', 'removed', 'ready', 'stop', 'error'] |
| 18 | + relatedPublish[key] = value |
| 19 | + |
| 20 | + # If there are any extra fields which do not exist in recreated related publish |
| 21 | + # (because they were added by some other code), copy them over |
| 22 | + # TODO: This copies also @related, test how recursive @related works |
| 23 | + for own key, value of publish when key not of relatedPublish |
| 24 | + relatedPublish[key] = value |
| 25 | + |
| 26 | + relatedPublishAdded = relatedPublish.added |
| 27 | + relatedPublish.added = (collectionName, id, fields) -> |
| 28 | + stringId = @_idFilter.idStringify id |
| 29 | + # If document as already present in oldRelatedPublish then we just set |
| 30 | + # relatedPublish's _documents and call changed to send updated fields |
| 31 | + # (Meteor sends only a diff). |
| 32 | + if oldRelatedPublish?._documents[collectionName]?[stringId] |
| 33 | + Meteor._ensure(@_documents, collectionName)[stringId] = true |
| 34 | + @changed collectionName, id, fields |
| 35 | + else |
| 36 | + relatedPublishAdded.call @, collectionName, id, fields |
| 37 | + |
| 38 | + relatedPublish.ready = -> |
| 39 | + # Mark it as ready only the first time |
| 40 | + publish.ready() unless ready |
| 41 | + ready = true |
| 42 | + # To return nothing. |
| 43 | + return |
| 44 | + |
| 45 | + relatedPublish.stop = (relatedChange) -> |
| 46 | + if relatedChange |
| 47 | + # We only deactivate (which calls stop callbacks as well) because we |
| 48 | + # have manually removed only documents which are not published again. |
| 49 | + @_deactivate() |
| 50 | + else |
| 51 | + # We do manually what would _stopSubscription do, but without |
| 52 | + # subscription handling. This should be done by the parent publish. |
| 53 | + @_removeAllDocuments() |
| 54 | + @_deactivate() |
| 55 | + publish.stop() |
| 56 | + # To return nothing. |
| 57 | + return |
| 58 | + |
| 59 | + relatedPublish._handler = publishFunction |
| 60 | + relatedPublish._runHandler() |
| 61 | + |
| 62 | + return unless oldRelatedPublish |
| 63 | + |
| 64 | + Tracker.nonreactive => |
| 65 | + # We remove those which are not published anymore |
| 66 | + for collectionName in _.keys(oldRelatedPublish._documents) |
| 67 | + for id in _.difference _.keys(oldRelatedPublish._documents[collectionName] or {}), _.keys(relatedPublish._documents[collectionName] or {}) |
| 68 | + oldRelatedPublish.removed collectionName, id |
| 69 | + |
| 70 | + oldRelatedPublish.stop true |
| 71 | + oldRelatedPublish = null |
| 72 | + |
| 73 | + handle = Tracker.autorun (computation) => |
| 74 | + publishDocuments() |
| 75 | + |
| 76 | + publish.onStop -> |
| 77 | + handle?.stop() |
| 78 | + handle = null |
| 79 | + relatedPublish?.stop() |
| 80 | + relatedPublish = null |
| 81 | + |
| 82 | + # To return nothing. |
| 83 | + return |
0 commit comments