inkwell 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. data/Rakefile +39 -0
  2. data/app/assets/javascripts/inkwell/application.js +9 -0
  3. data/app/assets/stylesheets/inkwell/application.css +7 -0
  4. data/app/controllers/inkwell/application_controller.rb +4 -0
  5. data/app/helpers/inkwell/application_helper.rb +4 -0
  6. data/app/models/inkwell/blog_item.rb +5 -0
  7. data/app/models/inkwell/comment.rb +125 -0
  8. data/app/models/inkwell/favorite_item.rb +5 -0
  9. data/app/models/inkwell/timeline_item.rb +5 -0
  10. data/app/views/layouts/inkwell/application.html.erb +14 -0
  11. data/config/routes.rb +3 -0
  12. data/db/migrate/20121202140510_create_inkwell_timeline_items.rb +13 -0
  13. data/db/migrate/20121202140816_add_columns_to_posts.rb +7 -0
  14. data/db/migrate/20121209121955_create_inkwell_blog_items.rb +12 -0
  15. data/db/migrate/20121209123557_create_inkwell_favorite_items.rb +11 -0
  16. data/db/migrate/20121209124435_add_columns_to_users.rb +6 -0
  17. data/db/migrate/20121209124743_create_inkwell_comments.rb +16 -0
  18. data/lib/acts_as_inkwell_post/base.rb +79 -0
  19. data/lib/acts_as_inkwell_user/base.rb +286 -0
  20. data/lib/common/base.rb +16 -0
  21. data/lib/inkwell.rb +7 -0
  22. data/lib/inkwell/engine.rb +5 -0
  23. data/lib/inkwell/version.rb +3 -0
  24. data/lib/tasks/inkwell_tasks.rake +4 -0
  25. data/test/dummy/Rakefile +7 -0
  26. data/test/dummy/app/assets/javascripts/application.js +9 -0
  27. data/test/dummy/app/assets/stylesheets/application.css +7 -0
  28. data/test/dummy/app/controllers/application_controller.rb +3 -0
  29. data/test/dummy/app/helpers/application_helper.rb +2 -0
  30. data/test/dummy/app/models/post.rb +5 -0
  31. data/test/dummy/app/models/user.rb +6 -0
  32. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  33. data/test/dummy/config.ru +4 -0
  34. data/test/dummy/config/application.rb +45 -0
  35. data/test/dummy/config/boot.rb +10 -0
  36. data/test/dummy/config/database.yml +25 -0
  37. data/test/dummy/config/environment.rb +5 -0
  38. data/test/dummy/config/environments/development.rb +30 -0
  39. data/test/dummy/config/environments/production.rb +60 -0
  40. data/test/dummy/config/environments/test.rb +39 -0
  41. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  42. data/test/dummy/config/initializers/inflections.rb +10 -0
  43. data/test/dummy/config/initializers/inkwell.rb +6 -0
  44. data/test/dummy/config/initializers/mime_types.rb +5 -0
  45. data/test/dummy/config/initializers/secret_token.rb +7 -0
  46. data/test/dummy/config/initializers/session_store.rb +8 -0
  47. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  48. data/test/dummy/config/locales/en.yml +5 -0
  49. data/test/dummy/config/routes.rb +4 -0
  50. data/test/dummy/db/migrate/20121202111750_create_posts.rb +11 -0
  51. data/test/dummy/db/migrate/20121202112556_create_users.rb +9 -0
  52. data/test/dummy/db/migrate/20130120124010_create_inkwell_timeline_items.rb +13 -0
  53. data/test/dummy/db/migrate/20130120124011_add_columns_to_posts.rb +7 -0
  54. data/test/dummy/db/migrate/20130120124012_create_inkwell_blog_items.rb +12 -0
  55. data/test/dummy/db/migrate/20130120124013_create_inkwell_favorite_items.rb +11 -0
  56. data/test/dummy/db/migrate/20130120124014_add_columns_to_users.rb +6 -0
  57. data/test/dummy/db/migrate/20130120124015_create_inkwell_comments.rb +16 -0
  58. data/test/dummy/db/schema.rb +75 -0
  59. data/test/dummy/db/seeds.rb +7 -0
  60. data/test/dummy/public/404.html +26 -0
  61. data/test/dummy/public/422.html +26 -0
  62. data/test/dummy/public/500.html +26 -0
  63. data/test/dummy/public/favicon.ico +0 -0
  64. data/test/dummy/script/rails +6 -0
  65. data/test/dummy/spec/functional/blogline_spec.rb +70 -0
  66. data/test/dummy/spec/functional/comments_spec.rb +396 -0
  67. data/test/dummy/spec/functional/favorite_spec.rb +236 -0
  68. data/test/dummy/spec/functional/following_spec.rb +120 -0
  69. data/test/dummy/spec/functional/reblog_spec.rb +153 -0
  70. data/test/dummy/spec/functional/timeline_spec.rb +68 -0
  71. data/test/dummy/spec/spec_helper.rb +52 -0
  72. metadata +229 -0
data/Rakefile ADDED
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+ begin
8
+ require 'rdoc/task'
9
+ rescue LoadError
10
+ require 'rdoc/rdoc'
11
+ require 'rake/rdoctask'
12
+ RDoc::Task = Rake::RDocTask
13
+ end
14
+
15
+ RDoc::Task.new(:rdoc) do |rdoc|
16
+ rdoc.rdoc_dir = 'rdoc'
17
+ rdoc.title = 'Inkwell'
18
+ rdoc.options << '--line-numbers'
19
+ rdoc.rdoc_files.include('README.rdoc')
20
+ rdoc.rdoc_files.include('lib/**/*.rb')
21
+ end
22
+
23
+ APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
24
+ load 'rails/tasks/engine.rake'
25
+
26
+
27
+ Bundler::GemHelper.install_tasks
28
+
29
+ require 'rake/testtask'
30
+
31
+ Rake::TestTask.new(:test) do |t|
32
+ t.libs << 'lib'
33
+ t.libs << 'test'
34
+ t.pattern = 'test/**/*_test.rb'
35
+ t.verbose = false
36
+ end
37
+
38
+
39
+ task :default => :test
@@ -0,0 +1,9 @@
1
+ // This is a manifest file that'll be compiled into including all the files listed below.
2
+ // Add new JavaScript/Coffee code in separate files in this directory and they'll automatically
3
+ // be included in the compiled file accessible from http://example.com/assets/application.js
4
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
5
+ // the compiled file.
6
+ //
7
+ //= require jquery
8
+ //= require jquery_ujs
9
+ //= require_tree .
@@ -0,0 +1,7 @@
1
+ /*
2
+ * This is a manifest file that'll automatically include all the stylesheets available in this directory
3
+ * and any sub-directories. You're free to add application-wide styles to this file and they'll appear at
4
+ * the top of the compiled file, but it's generally better to create a new file per style scope.
5
+ *= require_self
6
+ *= require_tree .
7
+ */
@@ -0,0 +1,4 @@
1
+ module Inkwell
2
+ class ApplicationController < ActionController::Base
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Inkwell
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1,5 @@
1
+ module Inkwell
2
+ class BlogItem < ActiveRecord::Base
3
+ belongs_to ::Inkwell::Engine::config.user_table.to_s.singularize
4
+ end
5
+ end
@@ -0,0 +1,125 @@
1
+ module Inkwell
2
+ class Comment < ActiveRecord::Base
3
+ attr_accessor :is_reblogged
4
+ attr_accessor :is_favorited
5
+ attr_accessor :item_id_in_line
6
+ attr_accessor :is_reblog_in_blogline
7
+ attr_accessor :from_sources_in_timeline
8
+
9
+ validates :"#{::Inkwell::Engine::config.post_table.to_s.singularize}_id", :presence => true
10
+ validates :"#{::Inkwell::Engine::config.user_table.to_s.singularize}_id", :presence => true
11
+ validates :body, :presence => true
12
+
13
+ after_create :processing_a_comment
14
+ before_destroy :destroy_comment_processing
15
+
16
+ belongs_to ::Inkwell::Engine::config.user_table.to_s.singularize
17
+ belongs_to ::Inkwell::Engine::config.post_table.to_s.singularize
18
+
19
+ def commentline(last_shown_comment_id = nil, limit = 10, for_user = nil)
20
+ if for_user
21
+ user_class = Object.const_get ::Inkwell::Engine::config.user_table.to_s.singularize.capitalize
22
+ raise "for_user param should be a #{user_class.to_s} but it is #{for_user.class.to_s}" unless for_user.class == user_class
23
+ end
24
+ users_ids_who_comment_it = ActiveSupport::JSON.decode self.users_ids_who_comment_it
25
+ if last_shown_comment_id
26
+ last_shown_comment_index = users_ids_who_comment_it.index{|rec| rec["comment_id"] == last_shown_comment_id}
27
+ users_ids_who_comment_it = users_ids_who_comment_it[0..last_shown_comment_index-1]
28
+ end
29
+ result_comments_info = users_ids_who_comment_it.last(limit)
30
+ result = []
31
+ result_comments_info.each do |comment_info|
32
+ comment = ::Inkwell::Comment.find comment_info["comment_id"]
33
+ if for_user
34
+ comment.is_reblogged = (for_user.reblog? comment) ? true : false
35
+ comment.is_favorited = (for_user.favorite? comment) ? true : false
36
+ end
37
+ result << comment
38
+ end
39
+ result
40
+ end
41
+
42
+ protected
43
+
44
+ def remove_info_from_upper_comments(comments_info)
45
+ return unless self.parent_id
46
+ parent_comment = ::Inkwell::Comment.find self.parent_id
47
+ raise "There is no comment with id = #{self.parent_id}" unless parent_comment
48
+ users_ids_who_comment_it = ActiveSupport::JSON.decode parent_comment.users_ids_who_comment_it
49
+ users_ids_who_comment_it -= comments_info
50
+ parent_comment.users_ids_who_comment_it = ActiveSupport::JSON.encode users_ids_who_comment_it
51
+ parent_comment.save
52
+ parent_comment.remove_info_from_upper_comments(comments_info)
53
+ end
54
+
55
+ private
56
+
57
+ def destroy_comment_processing
58
+ child_comments = ActiveSupport::JSON.decode self.users_ids_who_comment_it
59
+ child_comments_ids_to_deleted = []
60
+ child_comments.each do |comment|
61
+ child_comments_ids_to_deleted << comment['comment_id']
62
+ end
63
+ ::Inkwell::Comment.delete child_comments_ids_to_deleted
64
+
65
+ comment_with_child_comments_ids_to_deleted = child_comments_ids_to_deleted << self.id
66
+ ::Inkwell::TimelineItem.destroy_all :item_id => comment_with_child_comments_ids_to_deleted, :is_comment => true
67
+ ::Inkwell::FavoriteItem.destroy_all :item_id => comment_with_child_comments_ids_to_deleted, :is_comment => true
68
+ ::Inkwell::BlogItem.destroy_all :item_id => comment_with_child_comments_ids_to_deleted, :is_comment => true
69
+
70
+ user_id = self.send("#{::Inkwell::Engine::config.user_table.to_s.singularize}_id")
71
+ comment_with_child_comments_info = child_comments << Hash['user_id' => user_id, 'comment_id' => self.id]
72
+ remove_info_from_upper_comments comment_with_child_comments_info
73
+
74
+ post_class = Object.const_get ::Inkwell::Engine::config.post_table.to_s.singularize.capitalize
75
+ post_id_attr = "#{::Inkwell::Engine::config.post_table.to_s.singularize}_id"
76
+ parent_post = post_class.find self.send post_id_attr
77
+ users_ids_who_comment_it = ActiveSupport::JSON.decode parent_post.users_ids_who_comment_it
78
+ users_ids_who_comment_it -= comment_with_child_comments_info
79
+ parent_post.users_ids_who_comment_it = ActiveSupport::JSON.encode users_ids_who_comment_it
80
+ parent_post.save
81
+ end
82
+
83
+ def processing_a_comment
84
+ self.users_ids_who_favorite_it = "[]"
85
+ self.users_ids_who_comment_it = "[]"
86
+ self.users_ids_who_reblog_it = "[]"
87
+ self.save
88
+
89
+ post_class = Object.const_get ::Inkwell::Engine::config.post_table.to_s.singularize.capitalize
90
+ post_id_attr = "#{::Inkwell::Engine::config.post_table.to_s.singularize}_id"
91
+ parent_post = post_class.find self.send post_id_attr
92
+ user_id = self.send "#{::Inkwell::Engine::config.user_table.to_s.singularize}_id"
93
+ users_ids_who_comment_it = ActiveSupport::JSON.decode parent_post.users_ids_who_comment_it
94
+ users_ids_who_comment_it << Hash['user_id' => user_id, 'comment_id' => self.id]
95
+ parent_post.users_ids_who_comment_it = ActiveSupport::JSON.encode users_ids_who_comment_it
96
+ parent_post.save
97
+
98
+ add_user_info_to_upper_comments
99
+ end
100
+
101
+ def add_user_info_to_upper_comments
102
+ if self.parent_id
103
+ parent_comment = ::Inkwell::Comment.find self.parent_id
104
+ raise "Comment with id #{comment.parent_id} is not found" unless parent_comment
105
+ parent_upper_comments_tree = ActiveSupport::JSON.decode parent_comment.upper_comments_tree
106
+ self_upper_comments_tree = parent_upper_comments_tree << parent_comment.id
107
+ self.upper_comments_tree = ActiveSupport::JSON.encode self_upper_comments_tree
108
+
109
+ user_id = self.send "#{::Inkwell::Engine::config.user_table.to_s.singularize}_id"
110
+
111
+ self_upper_comments_tree.each do |comment_id|
112
+ comment = ::Inkwell::Comment.find comment_id
113
+ users_ids_who_comment_it = ActiveSupport::JSON.decode comment.users_ids_who_comment_it
114
+ users_ids_who_comment_it << Hash['user_id' => user_id, 'comment_id' => self.id]
115
+ comment.users_ids_who_comment_it = ActiveSupport::JSON.encode users_ids_who_comment_it
116
+ comment.save
117
+ end
118
+ else
119
+ self.upper_comments_tree = ActiveSupport::JSON.encode []
120
+ end
121
+
122
+ self.save
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,5 @@
1
+ module Inkwell
2
+ class FavoriteItem < ActiveRecord::Base
3
+ belongs_to ::Inkwell::Engine::config.user_table.to_s.singularize
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module Inkwell
2
+ class TimelineItem < ActiveRecord::Base
3
+ belongs_to ::Inkwell::Engine::config.user_table.to_s.singularize
4
+ end
5
+ end
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Inkwell</title>
5
+ <%= stylesheet_link_tag "inkwell/application" %>
6
+ <%= javascript_include_tag "inkwell/application" %>
7
+ <%= csrf_meta_tags %>
8
+ </head>
9
+ <body>
10
+
11
+ <%= yield %>
12
+
13
+ </body>
14
+ </html>
data/config/routes.rb ADDED
@@ -0,0 +1,3 @@
1
+ Inkwell::Engine.routes.draw do
2
+
3
+ end
@@ -0,0 +1,13 @@
1
+ class CreateInkwellTimelineItems < ActiveRecord::Migration
2
+ def change
3
+ create_table :inkwell_timeline_items do |t|
4
+ t.integer :item_id
5
+ t.integer "#{::Inkwell::Engine::config.user_table.to_s.singularize}_id"
6
+ t.string :from_source
7
+ t.boolean :has_many_sources, :default => false
8
+ t.boolean :is_comment
9
+
10
+ t.timestamps
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,7 @@
1
+ class AddColumnsToPosts < ActiveRecord::Migration
2
+ def change
3
+ add_column ::Inkwell::Engine::config.post_table, :users_ids_who_favorite_it, :text, :default => '[]'
4
+ add_column ::Inkwell::Engine::config.post_table, :users_ids_who_comment_it, :text, :default => '[]'
5
+ add_column ::Inkwell::Engine::config.post_table, :users_ids_who_reblog_it, :text, :default => '[]'
6
+ end
7
+ end
@@ -0,0 +1,12 @@
1
+ class CreateInkwellBlogItems < ActiveRecord::Migration
2
+ def change
3
+ create_table :inkwell_blog_items do |t|
4
+ t.integer :item_id
5
+ t.integer "#{::Inkwell::Engine::config.user_table.to_s.singularize}_id"
6
+ t.boolean :is_reblog
7
+ t.boolean :is_comment
8
+
9
+ t.timestamps
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,11 @@
1
+ class CreateInkwellFavoriteItems < ActiveRecord::Migration
2
+ def change
3
+ create_table :inkwell_favorite_items do |t|
4
+ t.integer "item_id"
5
+ t.integer "#{::Inkwell::Engine::config.user_table.to_s.singularize}_id"
6
+ t.boolean "is_comment"
7
+
8
+ t.timestamps
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,6 @@
1
+ class AddColumnsToUsers < ActiveRecord::Migration
2
+ def change
3
+ add_column ::Inkwell::Engine::config.user_table, :followers_ids, :text, :default => '[]'
4
+ add_column ::Inkwell::Engine::config.user_table, :followings_ids, :text, :default => '[]'
5
+ end
6
+ end
@@ -0,0 +1,16 @@
1
+ class CreateInkwellComments < ActiveRecord::Migration
2
+ def change
3
+ create_table :inkwell_comments do |t|
4
+ t.integer "#{::Inkwell::Engine::config.user_table.to_s.singularize}_id"
5
+ t.text :body
6
+ t.integer :parent_id
7
+ t.integer "#{::Inkwell::Engine::config.post_table.to_s.singularize}_id"
8
+ t.text :upper_comments_tree
9
+ t.text :users_ids_who_favorite_it
10
+ t.text :users_ids_who_comment_it
11
+ t.text :users_ids_who_reblog_it
12
+
13
+ t.timestamps
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,79 @@
1
+ module Inkwell
2
+ module ActsAsInkwellPost
3
+ module Base
4
+ def self.included(klass)
5
+ klass.class_eval do
6
+ extend Config
7
+ end
8
+ end
9
+ end
10
+
11
+ module Config
12
+ def acts_as_inkwell_post
13
+ attr_accessor :is_reblogged
14
+ attr_accessor :is_favorited
15
+ attr_accessor :item_id_in_line
16
+ attr_accessor :is_reblog_in_blogline
17
+ attr_accessor :from_sources_in_timeline
18
+
19
+ after_create :processing_a_post
20
+ before_destroy :destroy_post_processing
21
+
22
+ has_many :comments, :class_name => 'Inkwell::Comment'
23
+
24
+ include ::Inkwell::ActsAsInkwellPost::InstanceMethods
25
+ end
26
+ end
27
+
28
+ module InstanceMethods
29
+ def commentline(last_shown_comment_id = nil, limit = 10, for_user = nil)
30
+ if last_shown_comment_id
31
+ comments = self.comments.where("created_at < ?", Inkwell::Comment.find(last_shown_comment_id).created_at).order("created_at DESC").limit(limit)
32
+ else
33
+ comments = self.comments.order("created_at DESC").limit(limit)
34
+ end
35
+
36
+ if for_user
37
+ user_class = Object.const_get ::Inkwell::Engine::config.user_table.to_s.singularize.capitalize
38
+ raise "for_user param should be a #{user_class.to_s} but it is #{for_user.class.to_s}" unless for_user.class == user_class
39
+ comments.each do |comment|
40
+ comment.is_reblogged = (for_user.reblog? comment) ? true : false
41
+ comment.is_favorited = (for_user.favorite? comment) ? true : false
42
+ end
43
+ end
44
+
45
+ comments.reverse!
46
+ end
47
+
48
+ private
49
+
50
+ def processing_a_post
51
+ user_class = Object.const_get ::Inkwell::Engine::config.user_table.to_s.singularize.capitalize
52
+ user_id_attr = "#{::Inkwell::Engine::config.user_table.to_s.singularize}_id"
53
+ user = user_class.find self.send(user_id_attr)
54
+ ::Inkwell::BlogItem.create :item_id => self.id, :is_reblog => false, user_id_attr => self.send(user_id_attr), :is_comment => false
55
+
56
+ user.followers_row.each do |user_id|
57
+ encode_sources = [ Hash['user_id' => user.id, 'type' => 'following'] ]
58
+ ::Inkwell::TimelineItem.create :item_id => self.id, user_id_attr => user_id, :is_comment => false,
59
+ :from_source => ActiveSupport::JSON.encode(encode_sources)
60
+ end
61
+ end
62
+
63
+ def destroy_post_processing
64
+ ::Inkwell::TimelineItem.destroy_all :item_id => self.id, :is_comment => false
65
+ ::Inkwell::FavoriteItem.destroy_all :item_id => self.id, :is_comment => false
66
+ ::Inkwell::BlogItem.destroy_all :item_id => self.id, :is_comment => false
67
+ comments = self.comments
68
+ comments.each do |comment|
69
+ ::Inkwell::TimelineItem.destroy_all :item_id => comment.id, :is_comment => true
70
+ ::Inkwell::FavoriteItem.destroy_all :item_id => comment.id, :is_comment => true
71
+ ::Inkwell::BlogItem.destroy_all :item_id => comment.id, :is_comment => true
72
+ ::Inkwell::Comment.delete comment
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+
79
+ ::ActiveRecord::Base.send :include, ::Inkwell::ActsAsInkwellPost::Base
@@ -0,0 +1,286 @@
1
+ module Inkwell
2
+ module ActsAsInkwellUser
3
+ module Base
4
+ def self.included(klass)
5
+ klass.class_eval do
6
+ extend Config
7
+ end
8
+ end
9
+ end
10
+
11
+ module Config
12
+ def acts_as_inkwell_user
13
+ has_many :comments, :class_name => 'Inkwell::Comment'
14
+ has_many :favorite_items, :class_name => 'Inkwell::FavoriteItem'
15
+ has_many :blog_items, :class_name => 'Inkwell::BlogItem'
16
+ has_many :timeline_items, :class_name => 'Inkwell::TimelineItem'
17
+ include ::Inkwell::ActsAsInkwellUser::InstanceMethods
18
+ include ::Inkwell::Common
19
+ end
20
+ end
21
+
22
+ module InstanceMethods
23
+ def blogline(last_shown_obj_id = nil, limit = 10, for_user = nil)
24
+ if last_shown_obj_id
25
+ blog_items = self.blog_items.where("created_at < ?", Inkwell::BlogItem.find(last_shown_obj_id).created_at).order("created_at DESC").limit(limit)
26
+ else
27
+ blog_items = self.blog_items.order("created_at DESC").limit(limit)
28
+ end
29
+
30
+ post_class = Object.const_get ::Inkwell::Engine::config.post_table.to_s.singularize.capitalize
31
+ result = []
32
+ blog_items.each do |item|
33
+ if item.is_comment
34
+ blog_obj = ::Inkwell::Comment.find item.item_id
35
+ else
36
+ blog_obj = post_class.find item.item_id
37
+ end
38
+
39
+ blog_obj.item_id_in_line = item.id
40
+ blog_obj.is_reblog_in_blogline = item.is_reblog
41
+
42
+ if for_user
43
+ blog_obj.is_reblogged = (for_user.reblog? blog_obj) ? true : false
44
+ blog_obj.is_favorited = (for_user.favorite? blog_obj) ? true : false
45
+ end
46
+
47
+ result << blog_obj
48
+ end
49
+ result
50
+ end
51
+
52
+ def favorite(obj)
53
+ return if self.favorite? obj
54
+
55
+ FavoriteItem.create :item_id => obj.id, :user_id => self.id, :is_comment => is_comment(obj)
56
+
57
+ users_ids_who_favorite_it = ActiveSupport::JSON.decode obj.users_ids_who_favorite_it
58
+ users_ids_who_favorite_it << self.id
59
+ obj.users_ids_who_favorite_it = ActiveSupport::JSON.encode users_ids_who_favorite_it
60
+ obj.save
61
+ end
62
+
63
+ def favorite?(obj)
64
+ user_id_attr = "#{::Inkwell::Engine::config.user_table.to_s.singularize}_id"
65
+ (FavoriteItem.send("find_by_item_id_and_is_comment_and_#{user_id_attr}", obj.id, is_comment(obj), self.id)) ? true : false
66
+ end
67
+
68
+ def unfavorite(obj)
69
+ return unless self.favorite? obj
70
+
71
+ user_id_attr = "#{::Inkwell::Engine::config.user_table.to_s.singularize}_id"
72
+ record = FavoriteItem.send "find_by_item_id_and_is_comment_and_#{user_id_attr}", obj.id, is_comment(obj), self.id
73
+ record.destroy
74
+
75
+ users_ids_who_favorite_it = ActiveSupport::JSON.decode obj.users_ids_who_favorite_it
76
+ users_ids_who_favorite_it.delete self.id
77
+ obj.users_ids_who_favorite_it = ActiveSupport::JSON.encode users_ids_who_favorite_it
78
+ obj.save
79
+ end
80
+
81
+ def favoriteline(last_shown_obj_id = nil, limit = 10, for_user = nil)
82
+ if last_shown_obj_id
83
+ favorites = self.favorite_items.where("created_at < ?", Inkwell::FavoriteItem.find(last_shown_obj_id).created_at).order("created_at DESC").limit(limit)
84
+ else
85
+ favorites = self.favorite_items.order("created_at DESC").limit(limit)
86
+ end
87
+
88
+ post_class = Object.const_get ::Inkwell::Engine::config.post_table.to_s.singularize.capitalize
89
+ result = []
90
+ favorites.each do |item|
91
+ if item.is_comment
92
+ favorited_obj = ::Inkwell::Comment.find item.item_id
93
+ else
94
+ favorited_obj = post_class.find item.item_id
95
+ end
96
+
97
+ favorited_obj.item_id_in_line = item.id
98
+
99
+ if for_user
100
+ favorited_obj.is_reblogged = (for_user.reblog? favorited_obj) ? true : false
101
+ favorited_obj.is_favorited = (for_user.favorite? favorited_obj) ? true : false
102
+ end
103
+
104
+ result << favorited_obj
105
+ end
106
+ result
107
+ end
108
+
109
+ def follow(user)
110
+ return if self.follow? user
111
+ raise "User tries to follow himself." if self == user
112
+
113
+ followers = ActiveSupport::JSON.decode user.followers_ids
114
+ followers = followers << self.id
115
+ user.followers_ids = ActiveSupport::JSON.encode followers
116
+ user.save
117
+
118
+ followings = ActiveSupport::JSON.decode self.followings_ids
119
+ followings << user.id
120
+ self.followings_ids = ActiveSupport::JSON.encode followings
121
+ self.save
122
+
123
+ user_id_attr = "#{::Inkwell::Engine::config.user_table.to_s.singularize}_id"
124
+ user.blog_items.order("created_at DESC").limit(10).each do |blog_item|
125
+ next if blog_item.send(user_id_attr) == self.id
126
+ item = ::Inkwell::TimelineItem.send "find_by_item_id_and_#{user_id_attr}_and_is_comment", blog_item.item_id, self.id, blog_item.is_comment
127
+ if item
128
+ item.has_many_sources = true unless item.has_many_sources
129
+ sources = ActiveSupport::JSON.decode item.from_source
130
+ if blog_item.is_reblog
131
+ sources << Hash['user_id' => user.id, 'type' => 'reblog']
132
+ else
133
+ sources << Hash['user_id' => user.id, 'type' => 'following']
134
+ end
135
+ item.from_source = ActiveSupport::JSON.encode sources
136
+ item.save
137
+ else
138
+ sources = []
139
+ if blog_item.is_reblog
140
+ sources << Hash['user_id' => user.id, 'type' => 'reblog']
141
+ else
142
+ sources << Hash['user_id' => user.id, 'type' => 'following']
143
+ end
144
+ ::Inkwell::TimelineItem.create :item_id => blog_item.item_id, :is_comment => blog_item.is_comment, :user_id => self.id,
145
+ :from_source => ActiveSupport::JSON.encode(sources), :created_at => blog_item.created_at
146
+ end
147
+ end
148
+ end
149
+
150
+ def unfollow(user)
151
+ return unless self.follow? user
152
+ raise "User tries to unfollow himself." if self == user
153
+
154
+ followers = ActiveSupport::JSON.decode user.followers_ids
155
+ followers.delete self.id
156
+ user.followers_ids = ActiveSupport::JSON.encode followers
157
+ user.save
158
+
159
+ followings = ActiveSupport::JSON.decode self.followings_ids
160
+ followings.delete user.id
161
+ self.followings_ids = ActiveSupport::JSON.encode followings
162
+ self.save
163
+
164
+ user_id_attr = "#{::Inkwell::Engine::config.user_table.to_s.singularize}_id"
165
+
166
+ timeline_items = ::Inkwell::TimelineItem.where "from_source like '%{\"user_id\":#{user.id}%' and #{user_id_attr} = #{self.id}"
167
+ timeline_items.destroy_all :has_many_sources => false
168
+ timeline_items.each do |item|
169
+ from_source = ActiveSupport::JSON.decode item.from_source
170
+ from_source.delete_if { |rec| rec['user_id'] == user.id }
171
+ item.from_source = ActiveSupport::JSON.encode from_source
172
+ item.has_many_sources = false if from_source.size < 2
173
+ item.save
174
+ end
175
+ end
176
+
177
+ def follow?(user)
178
+ followings = ActiveSupport::JSON.decode self.followings_ids
179
+ followings.include? user.id
180
+ end
181
+
182
+ def followers_row
183
+ ActiveSupport::JSON.decode self.followers_ids
184
+ end
185
+
186
+ def followings_row
187
+ ActiveSupport::JSON.decode self.followings_ids
188
+ end
189
+
190
+ def reblog(obj)
191
+ return if self.reblog? obj
192
+ raise "User tries to reblog his post." if self.id == obj.user_id
193
+
194
+ is_comment = is_comment(obj)
195
+
196
+ user_id_attr = "#{::Inkwell::Engine::config.user_table.to_s.singularize}_id"
197
+ BlogItem.create :item_id => obj.id, :is_reblog => true, user_id_attr => self.id, :is_comment => is_comment
198
+
199
+ users_ids_who_reblog_it = ActiveSupport::JSON.decode obj.users_ids_who_reblog_it
200
+ users_ids_who_reblog_it << self.id
201
+ obj.users_ids_who_reblog_it = ActiveSupport::JSON.encode users_ids_who_reblog_it
202
+ obj.save
203
+
204
+ self.followers_row.each do |user_id|
205
+ next if obj.send(user_id_attr) == user_id
206
+ item = TimelineItem.send "find_by_item_id_and_#{user_id_attr}_and_is_comment", obj.id, user_id, is_comment
207
+ if item
208
+ item.has_many_sources = true unless item.has_many_sources
209
+ sources = ActiveSupport::JSON.decode item.from_source
210
+ sources << Hash['user_id' => self.id, 'type' => 'reblog']
211
+ item.from_source = ActiveSupport::JSON.encode sources
212
+ item.save
213
+ else
214
+ encode_sources = ActiveSupport::JSON.encode [Hash['user_id' => self.id, 'type' => 'reblog']]
215
+ TimelineItem.create :item_id => obj.id, :created_at => obj.created_at, user_id_attr => user_id, :from_source => encode_sources, :is_comment => is_comment
216
+ end
217
+ end
218
+ end
219
+
220
+ def reblog?(obj)
221
+ user_id_attr = "#{::Inkwell::Engine::config.user_table.to_s.singularize}_id"
222
+ BlogItem.exists? :item_id => obj.id, user_id_attr => self.id, :is_reblog => true, :is_comment => is_comment(obj)
223
+ end
224
+
225
+ def unreblog(obj)
226
+ return unless self.reblog? obj
227
+ raise "User tries to unreblog his post." if self.id == obj.user_id
228
+
229
+ is_comment = is_comment(obj)
230
+
231
+ users_ids_who_reblog_it = ActiveSupport::JSON.decode obj.users_ids_who_reblog_it
232
+ users_ids_who_reblog_it.delete self.id
233
+ obj.users_ids_who_reblog_it = ActiveSupport::JSON.encode users_ids_who_reblog_it
234
+ obj.save
235
+
236
+ user_id_attr = "#{::Inkwell::Engine::config.user_table.to_s.singularize}_id"
237
+ blog_item = BlogItem.send "find_by_item_id_and_is_reblog_and_#{user_id_attr}_and_is_comment", obj.id, true, self.id, is_comment
238
+ blog_item.destroy
239
+
240
+ self.followers_row.each do |user_id|
241
+ item = TimelineItem.send "find_by_item_id_and_#{user_id_attr}_and_is_comment", obj.id, user_id, is_comment
242
+ if item.has_many_sources
243
+ sources = ActiveSupport::JSON.decode item.from_source
244
+ sources.delete Hash['user_id' => self.id, 'type' => 'reblog']
245
+ item.has_many_sources = false if sources.size < 2
246
+ item.from_source = ActiveSupport::JSON.encode sources
247
+ item.save
248
+ else
249
+ item.destroy
250
+ end
251
+ end
252
+ end
253
+
254
+ def timeline(last_shown_obj_id = nil, limit = 10, for_user = nil)
255
+ if last_shown_obj_id
256
+ timeline_items = self.timeline_items.where("created_at < ?", Inkwell::TimelineItem.find(last_shown_obj_id).created_at).order("created_at DESC").limit(limit)
257
+ else
258
+ timeline_items = self.timeline_items.order("created_at DESC").limit(limit)
259
+ end
260
+
261
+ post_class = Object.const_get ::Inkwell::Engine::config.post_table.to_s.singularize.capitalize
262
+ result = []
263
+ timeline_items.each do |item|
264
+ if item.is_comment
265
+ timeline_obj = ::Inkwell::Comment.find item.item_id
266
+ else
267
+ timeline_obj = post_class.find item.item_id
268
+ end
269
+
270
+ timeline_obj.item_id_in_line = item.id
271
+ timeline_obj.from_sources_in_timeline = item.from_source
272
+
273
+ if for_user
274
+ timeline_obj.is_reblogged = (for_user.reblog? timeline_obj) ? true : false
275
+ timeline_obj.is_favorited = (for_user.favorite? timeline_obj) ? true : false
276
+ end
277
+
278
+ result << timeline_obj
279
+ end
280
+ result
281
+ end
282
+ end
283
+ end
284
+ end
285
+
286
+ ::ActiveRecord::Base.send :include, ::Inkwell::ActsAsInkwellUser::Base