{"action":"created","comment":{"url":"https://api.github.com/repos/Coursemology/coursemology2/pulls/comments/31310658","id":31310658,"diff_hunk":"@@ -0,0 +1,20 @@\n+module Course::ActivitiesConcern\n+  extend ActiveSupport::Concern\n+\n+  # Load recent activity feeds\n+  #\n+  # @param [Course] course course which activities are related to\n+  # @param [Hash]\n+  # @option [Integer] :number The number of activities that will be loaded","path":"app/controllers/concerns/course/activities_concern.rb","position":8,"original_position":8,"commit_id":"b86d7538468ef9ccbd64bb27471dcaddd6de1151","original_commit_id":"b86d7538468ef9ccbd64bb27471dcaddd6de1151","user":{"login":"lowjoel","id":2505070,"avatar_url":"https://avatars.githubusercontent.com/u/2505070?v=3","gravatar_id":"","url":"https://api.github.com/users/lowjoel","html_url":"https://github.com/lowjoel","followers_url":"https://api.github.com/users/lowjoel/followers","following_url":"https://api.github.com/users/lowjoel/following{/other_user}","gists_url":"https://api.github.com/users/lowjoel/gists{/gist_id}","starred_url":"https://api.github.com/users/lowjoel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lowjoel/subscriptions","organizations_url":"https://api.github.com/users/lowjoel/orgs","repos_url":"https://api.github.com/users/lowjoel/repos","events_url":"https://api.github.com/users/lowjoel/events{/privacy}","received_events_url":"https://api.github.com/users/lowjoel/received_events","type":"User","site_admin":false},"body":"Should be `@param` since it's now keyword arguments.","created_at":"2015-05-29T09:30:55Z","updated_at":"2015-05-29T09:30:55Z","html_url":"https://github.com/Coursemology/coursemology2/pull/189#discussion_r31310658","pull_request_url":"https://api.github.com/repos/Coursemology/coursemology2/pulls/189","_links":{"self":{"href":"https://api.github.com/repos/Coursemology/coursemology2/pulls/comments/31310658"},"html":{"href":"https://github.com/Coursemology/coursemology2/pull/189#discussion_r31310658"},"pull_request":{"href":"https://api.github.com/repos/Coursemology/coursemology2/pulls/189"}}},"pull_request":{"url":"https://api.github.com/repos/Coursemology/coursemology2/pulls/189","id":35233688,"html_url":"https://github.com/Coursemology/coursemology2/pull/189","diff_url":"https://github.com/Coursemology/coursemology2/pull/189.diff","patch_url":"https://github.com/Coursemology/coursemology2/pull/189.patch","issue_url":"https://api.github.com/repos/Coursemology/coursemology2/issues/189","number":189,"state":"open","locked":false,"title":"Redesign Notification Framework","user":{"login":"xzhflying","id":8858295,"avatar_url":"https://avatars.githubusercontent.com/u/8858295?v=3","gravatar_id":"","url":"https://api.github.com/users/xzhflying","html_url":"https://github.com/xzhflying","followers_url":"https://api.github.com/users/xzhflying/followers","following_url":"https://api.github.com/users/xzhflying/following{/other_user}","gists_url":"https://api.github.com/users/xzhflying/gists{/gist_id}","starred_url":"https://api.github.com/users/xzhflying/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/xzhflying/subscriptions","organizations_url":"https://api.github.com/users/xzhflying/orgs","repos_url":"https://api.github.com/users/xzhflying/repos","events_url":"https://api.github.com/users/xzhflying/events{/privacy}","received_events_url":"https://api.github.com/users/xzhflying/received_events","type":"User","site_admin":false},"body":"How to store data\r\n==============\r\n**Activity is a kind of record to note who did what. Notifications are based on activities. Since there are some activities then we need to notify users what happened. So the activities should have many kinds of notification styles**\r\n\r\nactivities table\r\n-------------------\r\nThis table is provided by public_activity gem which will mainly store:\r\n* owner:   We regard this field as the sender of this activity. Most of time should be course\r\n* trackable:   The object that is involved in this activity. (e.g. Achievement, Level ...)\r\n* recipient:   The receiver of this activity. Most of time should be User object.\r\n* key:   The key which indicates the path of template\r\n\r\nnotification_styles table\r\n------------------------\r\n* activity:  References activities table\r\n* notification_type: The style used to show the notification\r\n\r\nWhat if we just want to send a popup or any other notification types without an existing activity record? We can create a fake activity as the type of :notify. So that we can also store our data. And this kind of activity( :notify) will not be loaded when we want to load recent activities in course show page.\r\n\r\nTo create a notification:\r\n===================\r\nFirst you should add `acts_as_notifiable` in the **Model** that you want to send out notifications or activity feeds.( e.g. Level, achievement...)\r\nUse API: `object.notify(recipient, sender, types: {})`. Object stands for the instance of your model\r\nFor example, if you want to create three types of notifications based on a achievement object for a user in a course:\r\n`object.notify(user, course, types: { activity: :ActivityType, popup: true, email: true } )`\r\n\r\nThis notification is for a given user, so the recipient should be the user. Usually, most notifications are sent out by the course like (achievement, level, announcement). So the course should be the sender of this notification. \r\n\r\n`popup: , email: , activity:` are all optional. You can create any combinations of notifications among them. But it certainly doesn't make sense if you do not input any type.\r\n\r\npopup: \r\n---------------\r\nCould be set as enable by `popup: true`. After that You should provide styles in **view/ModelName/notifications/ActivityType/_popup** file. Activity type here will be the type that you input in the API's `activity:` field. If you did not filling this field, the Activity type will be **notify**\r\n\r\nemail: \r\n--------\r\nCould be set as enable by `email: true`. After that, you should provide email style in **view/ModelName/notifications/ActivityType/_email** file. In that file you may want to use `message.subject =` to set your email's subject. Meanwhile your email will also use **view/layouts/notifications/email.html.slim** as its layout.\r\n\r\nactivity:\r\n----------\r\nCould take in a **symbol** as the type name of activity. ( e.g. If one object is created in some controller, you may need to create an activity as `:created`) Activities are shown in course's show view. But you need to provide templates for each kind of activity type you have generated in **view/ModelName/notifications/ActivityType/_activity_feed** file. \r\n\r\nFor example, if someone reached some level. You may want to create an :updated activity for level object. To show this activity, you should provide the template. In that template, you may want to write:\r\n        `I18n.t('reached') a.trackable.level_number`  (you can use a.trackable to get your object record in your template)\r\n","created_at":"2015-05-12T14:45:20Z","updated_at":"2015-05-29T09:30:55Z","closed_at":null,"merged_at":null,"merge_commit_sha":"8ae488dc3af461bb01a65cfe4eead2af30d5a2d0","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/Coursemology/coursemology2/pulls/189/commits","review_comments_url":"https://api.github.com/repos/Coursemology/coursemology2/pulls/189/comments","review_comment_url":"https://api.github.com/repos/Coursemology/coursemology2/pulls/comments{/number}","comments_url":"https://api.github.com/repos/Coursemology/coursemology2/issues/189/comments","statuses_url":"https://api.github.com/repos/Coursemology/coursemology2/statuses/b86d7538468ef9ccbd64bb27471dcaddd6de1151","head":{"label":"xzhflying:notification","ref":"notification","sha":"b86d7538468ef9ccbd64bb27471dcaddd6de1151","user":{"login":"xzhflying","id":8858295,"avatar_url":"https://avatars.githubusercontent.com/u/8858295?v=3","gravatar_id":"","url":"https://api.github.com/users/xzhflying","html_url":"https://github.com/xzhflying","followers_url":"https://api.github.com/users/xzhflying/followers","following_url":"https://api.github.com/users/xzhflying/following{/other_user}","gists_url":"https://api.github.com/users/xzhflying/gists{/gist_id}","starred_url":"https://api.github.com/users/xzhflying/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/xzhflying/subscriptions","organizations_url":"https://api.github.com/users/xzhflying/orgs","repos_url":"https://api.github.com/users/xzhflying/repos","events_url":"https://api.github.com/users/xzhflying/events{/privacy}","received_events_url":"https://api.github.com/users/xzhflying/received_events","type":"User","site_admin":false},"repo":{"id":31704878,"name":"coursemology2","full_name":"xzhflying/coursemology2","owner":{"login":"xzhflying","id":8858295,"avatar_url":"https://avatars.githubusercontent.com/u/8858295?v=3","gravatar_id":"","url":"https://api.github.com/users/xzhflying","html_url":"https://github.com/xzhflying","followers_url":"https://api.github.com/users/xzhflying/followers","following_url":"https://api.github.com/users/xzhflying/following{/other_user}","gists_url":"https://api.github.com/users/xzhflying/gists{/gist_id}","starred_url":"https://api.github.com/users/xzhflying/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/xzhflying/subscriptions","organizations_url":"https://api.github.com/users/xzhflying/orgs","repos_url":"https://api.github.com/users/xzhflying/repos","events_url":"https://api.github.com/users/xzhflying/events{/privacy}","received_events_url":"https://api.github.com/users/xzhflying/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/xzhflying/coursemology2","description":"Rails 4 re-write of Coursemology","fork":true,"url":"https://api.github.com/repos/xzhflying/coursemology2","forks_url":"https://api.github.com/repos/xzhflying/coursemology2/forks","keys_url":"https://api.github.com/repos/xzhflying/coursemology2/keys{/key_id}","collaborators_url":"https://api.github.com/repos/xzhflying/coursemology2/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/xzhflying/coursemology2/teams","hooks_url":"https://api.github.com/repos/xzhflying/coursemology2/hooks","issue_events_url":"https://api.github.com/repos/xzhflying/coursemology2/issues/events{/number}","events_url":"https://api.github.com/repos/xzhflying/coursemology2/events","assignees_url":"https://api.github.com/repos/xzhflying/coursemology2/assignees{/user}","branches_url":"https://api.github.com/repos/xzhflying/coursemology2/branches{/branch}","tags_url":"https://api.github.com/repos/xzhflying/coursemology2/tags","blobs_url":"https://api.github.com/repos/xzhflying/coursemology2/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/xzhflying/coursemology2/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/xzhflying/coursemology2/git/refs{/sha}","trees_url":"https://api.github.com/repos/xzhflying/coursemology2/git/trees{/sha}","statuses_url":"https://api.github.com/repos/xzhflying/coursemology2/statuses/{sha}","languages_url":"https://api.github.com/repos/xzhflying/coursemology2/languages","stargazers_url":"https://api.github.com/repos/xzhflying/coursemology2/stargazers","contributors_url":"https://api.github.com/repos/xzhflying/coursemology2/contributors","subscribers_url":"https://api.github.com/repos/xzhflying/coursemology2/subscribers","subscription_url":"https://api.github.com/repos/xzhflying/coursemology2/subscription","commits_url":"https://api.github.com/repos/xzhflying/coursemology2/commits{/sha}","git_commits_url":"https://api.github.com/repos/xzhflying/coursemology2/git/commits{/sha}","comments_url":"https://api.github.com/repos/xzhflying/coursemology2/comments{/number}","issue_comment_url":"https://api.github.com/repos/xzhflying/coursemology2/issues/comments{/number}","contents_url":"https://api.github.com/repos/xzhflying/coursemology2/contents/{+path}","compare_url":"https://api.github.com/repos/xzhflying/coursemology2/compare/{base}...{head}","merges_url":"https://api.github.com/repos/xzhflying/coursemology2/merges","archive_url":"https://api.github.com/repos/xzhflying/coursemology2/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/xzhflying/coursemology2/downloads","issues_url":"https://api.github.com/repos/xzhflying/coursemology2/issues{/number}","pulls_url":"https://api.github.com/repos/xzhflying/coursemology2/pulls{/number}","milestones_url":"https://api.github.com/repos/xzhflying/coursemology2/milestones{/number}","notifications_url":"https://api.github.com/repos/xzhflying/coursemology2/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/xzhflying/coursemology2/labels{/name}","releases_url":"https://api.github.com/repos/xzhflying/coursemology2/releases{/id}","created_at":"2015-03-05T09:01:00Z","updated_at":"2015-03-30T12:53:21Z","pushed_at":"2015-05-29T07:33:04Z","git_url":"git://github.com/xzhflying/coursemology2.git","ssh_url":"git@github.com:xzhflying/coursemology2.git","clone_url":"https://github.com/xzhflying/coursemology2.git","svn_url":"https://github.com/xzhflying/coursemology2","homepage":null,"size":901,"stargazers_count":0,"watchers_count":0,"language":"Ruby","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"Coursemology:master","ref":"master","sha":"0b5410a7e78e53f053bcc22a9b7be8beda2065ff","user":{"login":"Coursemology","id":4427741,"avatar_url":"https://avatars.githubusercontent.com/u/4427741?v=3","gravatar_id":"","url":"https://api.github.com/users/Coursemology","html_url":"https://github.com/Coursemology","followers_url":"https://api.github.com/users/Coursemology/followers","following_url":"https://api.github.com/users/Coursemology/following{/other_user}","gists_url":"https://api.github.com/users/Coursemology/gists{/gist_id}","starred_url":"https://api.github.com/users/Coursemology/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Coursemology/subscriptions","organizations_url":"https://api.github.com/users/Coursemology/orgs","repos_url":"https://api.github.com/users/Coursemology/repos","events_url":"https://api.github.com/users/Coursemology/events{/privacy}","received_events_url":"https://api.github.com/users/Coursemology/received_events","type":"Organization","site_admin":false},"repo":{"id":22155032,"name":"coursemology2","full_name":"Coursemology/coursemology2","owner":{"login":"Coursemology","id":4427741,"avatar_url":"https://avatars.githubusercontent.com/u/4427741?v=3","gravatar_id":"","url":"https://api.github.com/users/Coursemology","html_url":"https://github.com/Coursemology","followers_url":"https://api.github.com/users/Coursemology/followers","following_url":"https://api.github.com/users/Coursemology/following{/other_user}","gists_url":"https://api.github.com/users/Coursemology/gists{/gist_id}","starred_url":"https://api.github.com/users/Coursemology/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Coursemology/subscriptions","organizations_url":"https://api.github.com/users/Coursemology/orgs","repos_url":"https://api.github.com/users/Coursemology/repos","events_url":"https://api.github.com/users/Coursemology/events{/privacy}","received_events_url":"https://api.github.com/users/Coursemology/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Coursemology/coursemology2","description":"Rails 4 re-write of Coursemology","fork":false,"url":"https://api.github.com/repos/Coursemology/coursemology2","forks_url":"https://api.github.com/repos/Coursemology/coursemology2/forks","keys_url":"https://api.github.com/repos/Coursemology/coursemology2/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Coursemology/coursemology2/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Coursemology/coursemology2/teams","hooks_url":"https://api.github.com/repos/Coursemology/coursemology2/hooks","issue_events_url":"https://api.github.com/repos/Coursemology/coursemology2/issues/events{/number}","events_url":"https://api.github.com/repos/Coursemology/coursemology2/events","assignees_url":"https://api.github.com/repos/Coursemology/coursemology2/assignees{/user}","branches_url":"https://api.github.com/repos/Coursemology/coursemology2/branches{/branch}","tags_url":"https://api.github.com/repos/Coursemology/coursemology2/tags","blobs_url":"https://api.github.com/repos/Coursemology/coursemology2/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Coursemology/coursemology2/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Coursemology/coursemology2/git/refs{/sha}","trees_url":"https://api.github.com/repos/Coursemology/coursemology2/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Coursemology/coursemology2/statuses/{sha}","languages_url":"https://api.github.com/repos/Coursemology/coursemology2/languages","stargazers_url":"https://api.github.com/repos/Coursemology/coursemology2/stargazers","contributors_url":"https://api.github.com/repos/Coursemology/coursemology2/contributors","subscribers_url":"https://api.github.com/repos/Coursemology/coursemology2/subscribers","subscription_url":"https://api.github.com/repos/Coursemology/coursemology2/subscription","commits_url":"https://api.github.com/repos/Coursemology/coursemology2/commits{/sha}","git_commits_url":"https://api.github.com/repos/Coursemology/coursemology2/git/commits{/sha}","comments_url":"https://api.github.com/repos/Coursemology/coursemology2/comments{/number}","issue_comment_url":"https://api.github.com/repos/Coursemology/coursemology2/issues/comments{/number}","contents_url":"https://api.github.com/repos/Coursemology/coursemology2/contents/{+path}","compare_url":"https://api.github.com/repos/Coursemology/coursemology2/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Coursemology/coursemology2/merges","archive_url":"https://api.github.com/repos/Coursemology/coursemology2/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Coursemology/coursemology2/downloads","issues_url":"https://api.github.com/repos/Coursemology/coursemology2/issues{/number}","pulls_url":"https://api.github.com/repos/Coursemology/coursemology2/pulls{/number}","milestones_url":"https://api.github.com/repos/Coursemology/coursemology2/milestones{/number}","notifications_url":"https://api.github.com/repos/Coursemology/coursemology2/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Coursemology/coursemology2/labels{/name}","releases_url":"https://api.github.com/repos/Coursemology/coursemology2/releases{/id}","created_at":"2014-07-23T14:57:06Z","updated_at":"2015-05-13T05:02:47Z","pushed_at":"2015-05-29T05:39:04Z","git_url":"git://github.com/Coursemology/coursemology2.git","ssh_url":"git@github.com:Coursemology/coursemology2.git","clone_url":"https://github.com/Coursemology/coursemology2.git","svn_url":"https://github.com/Coursemology/coursemology2","homepage":null,"size":5201,"stargazers_count":12,"watchers_count":12,"language":"Ruby","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":9,"mirror_url":null,"open_issues_count":50,"forks":9,"open_issues":50,"watchers":12,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/Coursemology/coursemology2/pulls/189"},"html":{"href":"https://github.com/Coursemology/coursemology2/pull/189"},"issue":{"href":"https://api.github.com/repos/Coursemology/coursemology2/issues/189"},"comments":{"href":"https://api.github.com/repos/Coursemology/coursemology2/issues/189/comments"},"review_comments":{"href":"https://api.github.com/repos/Coursemology/coursemology2/pulls/189/comments"},"review_comment":{"href":"https://api.github.com/repos/Coursemology/coursemology2/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/Coursemology/coursemology2/pulls/189/commits"},"statuses":{"href":"https://api.github.com/repos/Coursemology/coursemology2/statuses/b86d7538468ef9ccbd64bb27471dcaddd6de1151"}}}}