Commit 944106ba by tady

add watch model

parent abd35970
...@@ -87,6 +87,7 @@ group :development, :test do ...@@ -87,6 +87,7 @@ group :development, :test do
gem 'teaspoon' gem 'teaspoon'
gem 'guard-teaspoon' gem 'guard-teaspoon'
gem 'byebug'
end end
group :test do group :test do
......
...@@ -64,6 +64,9 @@ GEM ...@@ -64,6 +64,9 @@ GEM
breadcrumble (4.1.0) breadcrumble (4.1.0)
rails (>= 4.0.0) rails (>= 4.0.0)
builder (3.2.2) builder (3.2.2)
byebug (3.1.2)
columnize (~> 0.8)
debugger-linecache (~> 1.2)
capistrano (3.2.1) capistrano (3.2.1)
i18n i18n
rake (>= 10.0.0) rake (>= 10.0.0)
...@@ -95,6 +98,7 @@ GEM ...@@ -95,6 +98,7 @@ GEM
execjs execjs
coffee-script-source (1.7.1) coffee-script-source (1.7.1)
colorize (0.7.3) colorize (0.7.3)
columnize (0.8.9)
coveralls (0.7.0) coveralls (0.7.0)
multi_json (~> 1.3) multi_json (~> 1.3)
rest-client rest-client
...@@ -106,6 +110,7 @@ GEM ...@@ -106,6 +110,7 @@ GEM
daemons (1.1.9) daemons (1.1.9)
database_rewinder (0.2.0) database_rewinder (0.2.0)
debug_inspector (0.0.2) debug_inspector (0.0.2)
debugger-linecache (1.2.0)
devise (3.2.4) devise (3.2.4)
bcrypt (~> 3.0) bcrypt (~> 3.0)
orm_adapter (~> 0.1) orm_adapter (~> 0.1)
...@@ -391,6 +396,7 @@ DEPENDENCIES ...@@ -391,6 +396,7 @@ DEPENDENCIES
better_errors better_errors
binding_of_caller binding_of_caller
breadcrumble breadcrumble
byebug
capistrano (~> 3.1) capistrano (~> 3.1)
capistrano-bundler (~> 1.1.2) capistrano-bundler (~> 1.1.2)
capistrano-rails (~> 1.1) capistrano-rails (~> 1.1)
......
...@@ -110,9 +110,9 @@ class PostsController < ApplicationController ...@@ -110,9 +110,9 @@ class PostsController < ApplicationController
def watch def watch
if current_user.watching?(post: @post) if current_user.watching?(post: @post)
@post.watchers.where(user: current_user).destroy_all @post.watchings.where(user: current_user).destroy_all
else else
@post.watchers.create!(user: current_user) @post.watchings.create!(user: current_user)
end end
respond_to do |format| respond_to do |format|
......
...@@ -14,13 +14,21 @@ class Comment < ActiveRecord::Base ...@@ -14,13 +14,21 @@ class Comment < ActiveRecord::Base
belongs_to :author, class_name: 'User' belongs_to :author, class_name: 'User'
belongs_to :post belongs_to :post
######################################################################
# validations
######################################################################
validates :author_id, presence: true validates :author_id, presence: true
validates :post_id, presence: true validates :post_id, presence: true
validates :body, presence: true validates :body, presence: true
### Callback ### ######################################################################
# Callback
######################################################################
after_save :notify_author after_save :notify_author
######################################################################
# Instance method
######################################################################
private private
def notify_author def notify_author
......
# == Schema Information
#
# Table name: footprints
#
# id :integer not null, primary key
# user_id :integer not null
# post_id :integer not null
# created_at :datetime
# updated_at :datetime
#
class Footprint < ActiveRecord::Base class Footprint < ActiveRecord::Base
belongs_to :user belongs_to :user
belongs_to :post belongs_to :post
......
...@@ -21,9 +21,9 @@ class Post < ActiveRecord::Base ...@@ -21,9 +21,9 @@ class Post < ActiveRecord::Base
belongs_to :author, class_name: 'User' belongs_to :author, class_name: 'User'
has_many :comments has_many :comments
has_many :footprints has_many :footprints
has_many :watchers, :as => :resource
# default_scope { where(is_draft: false).order(:updated_at => :desc) } has_many :watches, :as => :watchable, :dependent => :destroy
has_many :watchers, :through => :watches
###################################################################### ######################################################################
# validations # validations
...@@ -32,6 +32,11 @@ class Post < ActiveRecord::Base ...@@ -32,6 +32,11 @@ class Post < ActiveRecord::Base
validates :body, presence: true validates :body, presence: true
###################################################################### ######################################################################
# Callback
######################################################################
after_save :notify_watchers
######################################################################
# Named scope # Named scope
###################################################################### ######################################################################
scope :search, (lambda do |query| scope :search, (lambda do |query|
...@@ -101,4 +106,12 @@ class Post < ActiveRecord::Base ...@@ -101,4 +106,12 @@ class Post < ActiveRecord::Base
def visited_user_count def visited_user_count
footprints.select(:user_id).uniq.count footprints.select(:user_id).uniq.count
end end
private
def notify_watchers
watchers.each do |watcher|
watcher.push_notification(decorate.show_path, "#{author.name}さんが「#{title}」を編集しました")
end
end
end end
...@@ -14,7 +14,9 @@ ...@@ -14,7 +14,9 @@
class Tag < ActiveRecord::Base class Tag < ActiveRecord::Base
has_many :post_tags has_many :post_tags
has_many :posts, through: :post_tags has_many :posts, through: :post_tags
has_many :watchers, :as => :resource
has_many :watches, :as => :watchable, :dependent => :destroy
has_many :watchers, :through => :watches
# for tree structure # for tree structure
has_ancestry has_ancestry
......
...@@ -39,8 +39,11 @@ class User < ActiveRecord::Base ...@@ -39,8 +39,11 @@ class User < ActiveRecord::Base
has_many :comments, foreign_key: 'author_id' has_many :comments, foreign_key: 'author_id'
has_many :notifications has_many :notifications
has_many :footprints has_many :footprints
has_many :watchings, class_name: 'Watcher'
has_many :watchers, :as => :resource has_many :watches
has_many :watchings, class_name: 'Watch', foreign_key: 'watcher_id'
has_many :watching_posts, :through => :watchings, :source => :watchable, :source_type => "Post"
# has_many :watchings, :as => :resource
###################################################################### ######################################################################
# scope # scope
...@@ -126,14 +129,14 @@ class User < ActiveRecord::Base ...@@ -126,14 +129,14 @@ class User < ActiveRecord::Base
# TODO: tag/user # TODO: tag/user
def watching?(hash) def watching?(hash)
if hash[:post] if hash[:post]
hash[:post].watchers.where(user_id: self.id).exists? hash[:post].watchings.where(user_id: self.id).exists?
else else
false false
end end
end end
def watching_posts # def watching_posts
ids = watchings.where(resource_type: "Post").pluck(:resource_id) # ids = watching_items.where(resource_type: "Post").pluck(:resource_id)
Post.where(id: ids) # Post.where(id: ids)
end # end
end end
class Watch < ActiveRecord::Base
belongs_to :watcher, class_name: 'User'
belongs_to :watchable, polymorphic: true
end
class Watcher < ActiveRecord::Base
belongs_to :user
belongs_to :resource, polymorphic: true
end
class CreateWatchers < ActiveRecord::Migration class CreateWatches < ActiveRecord::Migration
def change def change
create_table :watchers do |t| create_table :watches do |t|
t.integer :user_id, null: false t.integer :user_id, null: false
t.string :resource_type, null: false t.string :watchable_type, null: false
t.integer :resource_id, null: false t.integer :watchable_id, null: false
t.timestamps t.timestamps
end end
add_index :watchers, [:user_id, :resource_type, :resource_id], unique: true add_index :watches, [:user_id, :watchable_type, :watchable_id], unique: true
add_index :watchers, [:resource_type, :resource_id] add_index :watches, [:watchable_type, :watchable_id]
end end
end end
...@@ -115,15 +115,15 @@ ActiveRecord::Schema.define(version: 20140719145016) do ...@@ -115,15 +115,15 @@ ActiveRecord::Schema.define(version: 20140719145016) do
add_index "versions", ["item_type", "item_id"], name: "index_versions_on_item_type_and_item_id", using: :btree add_index "versions", ["item_type", "item_id"], name: "index_versions_on_item_type_and_item_id", using: :btree
create_table "watchers", force: true do |t| create_table "watches", force: true do |t|
t.integer "user_id", null: false t.integer "watcher_id", null: false
t.string "resource_type", null: false t.string "watchable_type", null: false
t.integer "resource_id", null: false t.integer "watchable_id", null: false
t.datetime "created_at" t.datetime "created_at"
t.datetime "updated_at" t.datetime "updated_at"
end end
add_index "watchers", ["resource_type", "resource_id"], name: "index_watchers_on_resource_type_and_resource_id", using: :btree add_index "watches", ["watchable_type", "watchable_id"], name: "index_watches_on_watchable_type_and_watchable_id", using: :btree
add_index "watchers", ["user_id", "resource_type", "resource_id"], name: "index_watchers_on_user_id_and_resource_type_and_resource_id", unique: true, using: :btree add_index "watches", ["watcher_id", "watchable_type", "watchable_id"], name: "index_watches_on_watcher_id_and_watchable_type_and_watchable_id", unique: true, using: :btree
end end
# == Schema Information
#
# Table name: footprints
#
# id :integer not null, primary key
# user_id :integer not null
# post_id :integer not null
# created_at :datetime
# updated_at :datetime
#
require 'rails_helper' require 'rails_helper'
RSpec.describe Footprint, :type => :model do RSpec.describe Footprint, :type => :model do
......
...@@ -109,7 +109,22 @@ describe Post do ...@@ -109,7 +109,22 @@ describe Post do
expect(Post.search('ruby')).to include(@post1) expect(Post.search('ruby')).to include(@post1)
expect(Post.search('ruby')).to include(@post3) expect(Post.search('ruby')).to include(@post3)
end end
end end
describe '#notify_watchers' do
before :each do
@alice = create(:alice)
@bob = create(:bob)
@post = @alice.posts.create id: 1001, title: 'ruby rspec', body: 'This is first espec test: ruby'
end
it do
@post.watchers << @bob
expect(@bob.watching_posts.size).to eq(1)
expect(@bob.notifications.size).to eq(0)
@post.update!(title: @post.title + '+')
expect(@bob.notifications.size).to eq(1)
end
end
end end
require 'rails_helper' require 'rails_helper'
RSpec.describe Watcher, :type => :model do RSpec.describe Watch, :type => :model do
pending "add some examples to (or delete) #{__FILE__}" pending "add some examples to (or delete) #{__FILE__}"
end end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment