Commit 944106ba by tady

add watch model

parent abd35970
......@@ -87,6 +87,7 @@ group :development, :test do
gem 'teaspoon'
gem 'guard-teaspoon'
gem 'byebug'
end
group :test do
......
......@@ -64,6 +64,9 @@ GEM
breadcrumble (4.1.0)
rails (>= 4.0.0)
builder (3.2.2)
byebug (3.1.2)
columnize (~> 0.8)
debugger-linecache (~> 1.2)
capistrano (3.2.1)
i18n
rake (>= 10.0.0)
......@@ -95,6 +98,7 @@ GEM
execjs
coffee-script-source (1.7.1)
colorize (0.7.3)
columnize (0.8.9)
coveralls (0.7.0)
multi_json (~> 1.3)
rest-client
......@@ -106,6 +110,7 @@ GEM
daemons (1.1.9)
database_rewinder (0.2.0)
debug_inspector (0.0.2)
debugger-linecache (1.2.0)
devise (3.2.4)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
......@@ -391,6 +396,7 @@ DEPENDENCIES
better_errors
binding_of_caller
breadcrumble
byebug
capistrano (~> 3.1)
capistrano-bundler (~> 1.1.2)
capistrano-rails (~> 1.1)
......
......@@ -110,9 +110,9 @@ class PostsController < ApplicationController
def watch
if current_user.watching?(post: @post)
@post.watchers.where(user: current_user).destroy_all
@post.watchings.where(user: current_user).destroy_all
else
@post.watchers.create!(user: current_user)
@post.watchings.create!(user: current_user)
end
respond_to do |format|
......
......@@ -14,13 +14,21 @@ class Comment < ActiveRecord::Base
belongs_to :author, class_name: 'User'
belongs_to :post
######################################################################
# validations
######################################################################
validates :author_id, presence: true
validates :post_id, presence: true
validates :body, presence: true
### Callback ###
######################################################################
# Callback
######################################################################
after_save :notify_author
######################################################################
# Instance method
######################################################################
private
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
belongs_to :user
belongs_to :post
......
......@@ -21,9 +21,9 @@ class Post < ActiveRecord::Base
belongs_to :author, class_name: 'User'
has_many :comments
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
......@@ -32,6 +32,11 @@ class Post < ActiveRecord::Base
validates :body, presence: true
######################################################################
# Callback
######################################################################
after_save :notify_watchers
######################################################################
# Named scope
######################################################################
scope :search, (lambda do |query|
......@@ -101,4 +106,12 @@ class Post < ActiveRecord::Base
def visited_user_count
footprints.select(:user_id).uniq.count
end
private
def notify_watchers
watchers.each do |watcher|
watcher.push_notification(decorate.show_path, "#{author.name}さんが「#{title}」を編集しました")
end
end
end
......@@ -14,7 +14,9 @@
class Tag < ActiveRecord::Base
has_many :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
has_ancestry
......
......@@ -39,8 +39,11 @@ class User < ActiveRecord::Base
has_many :comments, foreign_key: 'author_id'
has_many :notifications
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
......@@ -126,14 +129,14 @@ class User < ActiveRecord::Base
# TODO: tag/user
def watching?(hash)
if hash[:post]
hash[:post].watchers.where(user_id: self.id).exists?
hash[:post].watchings.where(user_id: self.id).exists?
else
false
end
end
def watching_posts
ids = watchings.where(resource_type: "Post").pluck(:resource_id)
Post.where(id: ids)
end
# def watching_posts
# ids = watching_items.where(resource_type: "Post").pluck(:resource_id)
# Post.where(id: ids)
# 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
create_table :watchers do |t|
create_table :watches do |t|
t.integer :user_id, null: false
t.string :resource_type, null: false
t.integer :resource_id, null: false
t.string :watchable_type, null: false
t.integer :watchable_id, null: false
t.timestamps
end
add_index :watchers, [:user_id, :resource_type, :resource_id], unique: true
add_index :watchers, [:resource_type, :resource_id]
add_index :watches, [:user_id, :watchable_type, :watchable_id], unique: true
add_index :watches, [:watchable_type, :watchable_id]
end
end
......@@ -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
create_table "watchers", force: true do |t|
t.integer "user_id", null: false
t.string "resource_type", null: false
t.integer "resource_id", null: false
create_table "watches", force: true do |t|
t.integer "watcher_id", null: false
t.string "watchable_type", null: false
t.integer "watchable_id", null: false
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "watchers", ["resource_type", "resource_id"], name: "index_watchers_on_resource_type_and_resource_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", ["watchable_type", "watchable_id"], name: "index_watches_on_watchable_type_and_watchable_id", 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
# == 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'
RSpec.describe Footprint, :type => :model do
......
......@@ -109,7 +109,22 @@ describe Post do
expect(Post.search('ruby')).to include(@post1)
expect(Post.search('ruby')).to include(@post3)
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
require 'rails_helper'
RSpec.describe Watcher, :type => :model do
RSpec.describe Watch, :type => :model do
pending "add some examples to (or delete) #{__FILE__}"
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