nt_models 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/db/migrate/20190225192049_create_user_table.rb +10 -0
- data/db/migrate/20190225201314_create_tweet_table.rb +10 -0
- data/db/migrate/20190226212517_create_tweet_tag_table.rb +9 -0
- data/db/migrate/20190226212626_create_hashtag_table.rb +8 -0
- data/db/migrate/20190226212645_create_timeline_piece_table.rb +9 -0
- data/db/migrate/20190226212658_create_mention_table.rb +9 -0
- data/db/migrate/20190226212737_create_follow_table.rb +9 -0
- data/db/migrate/nt_models.rb +1 -0
- data/db/schema.rb +54 -0
- data/lib/models/follow.rb +11 -0
- data/lib/models/hashtag.rb +5 -0
- data/lib/models/mention.rb +5 -0
- data/lib/models/timeline_piece.rb +5 -0
- data/lib/models/tweet.rb +10 -0
- data/lib/models/tweet_tag.rb +5 -0
- data/lib/models/user.rb +20 -0
- data/lib/nt_models.rb +8 -0
- data/test/follow_test.rb +60 -0
- data/test/test_helper.rb +23 -0
- data/test/tweet_test.rb +16 -0
- data/test/user_test.rb +30 -0
- metadata +161 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 67ab343ca340b88ae74a308e0b48defb99d18eeb
|
4
|
+
data.tar.gz: 719e23d3548c5f1f70614293afc8b03de0d68ce1
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8cc798e18e5d20c28f463a2e04fb258a5a4da3ed0c3efffeb3e88780aa1571d6677a76fc6021b405761d57aaef80270bc54f3f4bad951ba5a450a6faae9d9ba6
|
7
|
+
data.tar.gz: 51a970a183e3eb3c59a38a01fd06a9dffbf160a130a40e6409d74848f382753707136b944f16aabb8157dfab704ba34ebe8c0b5a5997010d5e5792c8003a5944
|
@@ -0,0 +1 @@
|
|
1
|
+
Dir["#{__dir__}/models/*.rb"].each { |file| require file }
|
data/db/schema.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
# This file is auto-generated from the current state of the database. Instead
|
2
|
+
# of editing this file, please use the migrations feature of Active Record to
|
3
|
+
# incrementally modify your database, and then regenerate this schema definition.
|
4
|
+
#
|
5
|
+
# Note that this schema.rb definition is the authoritative source for your
|
6
|
+
# database schema. If you need to create the application database on another
|
7
|
+
# system, you should be using db:schema:load, not running all the migrations
|
8
|
+
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
|
9
|
+
# you'll amass, the slower it'll run and the greater likelihood for issues).
|
10
|
+
#
|
11
|
+
# It's strongly recommended that you check this file into your version control system.
|
12
|
+
|
13
|
+
ActiveRecord::Schema.define(version: 2019_02_26_212737) do
|
14
|
+
|
15
|
+
# These are extensions that must be enabled in order to support this database
|
16
|
+
enable_extension "plpgsql"
|
17
|
+
|
18
|
+
create_table "follows", force: :cascade do |t|
|
19
|
+
t.integer "follower_id"
|
20
|
+
t.integer "followee_id"
|
21
|
+
end
|
22
|
+
|
23
|
+
create_table "hashtags", force: :cascade do |t|
|
24
|
+
t.text "name"
|
25
|
+
end
|
26
|
+
|
27
|
+
create_table "mentions", force: :cascade do |t|
|
28
|
+
t.integer "tweet_id"
|
29
|
+
t.integer "mentioned_user_id"
|
30
|
+
end
|
31
|
+
|
32
|
+
create_table "timeline_pieces", force: :cascade do |t|
|
33
|
+
t.integer "timeline_owner_id"
|
34
|
+
t.integer "tweet_id"
|
35
|
+
end
|
36
|
+
|
37
|
+
create_table "tweet_tags", force: :cascade do |t|
|
38
|
+
t.integer "hashtag_id"
|
39
|
+
t.integer "tweet_id"
|
40
|
+
end
|
41
|
+
|
42
|
+
create_table "tweets", force: :cascade do |t|
|
43
|
+
t.string "body"
|
44
|
+
t.datetime "created_on"
|
45
|
+
t.integer "author_id"
|
46
|
+
end
|
47
|
+
|
48
|
+
create_table "users", force: :cascade do |t|
|
49
|
+
t.string "name"
|
50
|
+
t.string "handle"
|
51
|
+
t.string "password_digest"
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# Represents the db's Follow table
|
2
|
+
class Follow < ActiveRecord::Base
|
3
|
+
belongs_to :follower, class_name: 'User'
|
4
|
+
belongs_to :followee, class_name: 'User'
|
5
|
+
|
6
|
+
# No two follows should have the same follower and followee
|
7
|
+
validates_uniqueness_of :follower_id, scope: %i[followee_id]
|
8
|
+
|
9
|
+
# Follower != Followee (user can't follow themselves)
|
10
|
+
validates :follower_id, exclusion: { in: ->(follow) { [follow.followee_id] } }
|
11
|
+
end
|
data/lib/models/tweet.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
# Represents the db's Tweet table
|
2
|
+
class Tweet < ActiveRecord::Base
|
3
|
+
belongs_to :author, class_name: 'User', foreign_key: :author_id
|
4
|
+
has_many :tweet_tags
|
5
|
+
has_many :hashtags, through: :tweet_tags
|
6
|
+
has_many :mentions
|
7
|
+
has_many :mentioned_users, through: :mentions
|
8
|
+
has_many :timeline_pieces
|
9
|
+
has_many :timeline_users, through: :timeline_pieces, source: :timeline_owner
|
10
|
+
end
|
data/lib/models/user.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# Represents the db's User table
|
2
|
+
class User < ActiveRecord::Base
|
3
|
+
has_secure_password
|
4
|
+
validates :handle, presence: true, uniqueness: true
|
5
|
+
|
6
|
+
has_many :follows_from_me, class_name: 'Follow', foreign_key: :follower_id
|
7
|
+
has_many :followees, through: :follows_from_me
|
8
|
+
|
9
|
+
# Followers are people who follow this user
|
10
|
+
has_many :follows_to_me, class_name: 'Follow', foreign_key: :followee_id
|
11
|
+
has_many :followers, through: :follows_to_me
|
12
|
+
|
13
|
+
has_many :tweets, foreign_key: :author_id
|
14
|
+
has_many :tweet_tags, through: :tweets
|
15
|
+
has_many :timeline_pieces, foreign_key: :timeline_owner_id
|
16
|
+
has_many :timeline_tweets, through: :timeline_pieces, source: :tweet
|
17
|
+
has_many :mentions, foreign_key: :mentioned_user_id
|
18
|
+
has_many :mentioned_tweets, through: :mentions, source: :tweet
|
19
|
+
|
20
|
+
end
|
data/lib/nt_models.rb
ADDED
data/test/follow_test.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
def follow(follower, followee)
|
2
|
+
Follow.create(follower: follower, followee: followee)
|
3
|
+
end
|
4
|
+
|
5
|
+
describe 'follows' do
|
6
|
+
before do
|
7
|
+
follow(@brad, @ari)
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'can tell how many people are following Ari' do
|
11
|
+
@ari.followers.count.must_equal 1
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'can tell how many people Brad is following' do
|
15
|
+
@brad.followees.count.must_equal 1
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'can handle multiple followers' do
|
19
|
+
[@yang, @pito].each { |u| follow(u, @ari) }
|
20
|
+
@ari.followers.count.must_equal 3
|
21
|
+
[@brad, @yang, @pito].each { |u| u.followees.count.must_equal 1 }
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'can handle multiple followees' do
|
25
|
+
[@yang, @pito].each { |u| follow(@brad, u) }
|
26
|
+
@brad.followees.count.must_equal 3
|
27
|
+
[@ari, @yang, @pito].each { |u| u.followers.count.must_equal 1 }
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'will not let Brad follow Ari twice' do
|
31
|
+
f = Follow.new(follower_id: @brad.id, followee_id: @ari.id)
|
32
|
+
f.save.must_equal false
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'will not let Ari follow himself' do
|
36
|
+
f = Follow.new(follower_id: @ari.id, followee_id: @ari.id)
|
37
|
+
f.save.must_equal false
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'will let Ari follow Brad even though Brad already follows Ari' do
|
41
|
+
f = Follow.new(follower_id: @ari.id, followee_id: @brad.id)
|
42
|
+
f.save.must_equal true
|
43
|
+
@ari.followees.count.must_equal 1
|
44
|
+
@brad.followers.count.must_equal 1
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'will let follows be created from the follower' do
|
48
|
+
@ari.followees << @brad
|
49
|
+
Follow.count.must_equal 2
|
50
|
+
@ari.followees.count.must_equal 1
|
51
|
+
@brad.followers.count.must_equal 1
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'will let follows be created from the followee' do
|
55
|
+
@brad.followers << @ari
|
56
|
+
Follow.count.must_equal 2
|
57
|
+
@ari.followees.count.must_equal 1
|
58
|
+
@brad.followers.count.must_equal 1
|
59
|
+
end
|
60
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# This file is a DRY way to set all of the requirements
|
2
|
+
# that our tests will need, as well as a before statement
|
3
|
+
# that purges the database and creates fixtures before every test
|
4
|
+
|
5
|
+
ENV['APP_ENV'] = 'test'
|
6
|
+
require 'simplecov'
|
7
|
+
SimpleCov.start
|
8
|
+
require 'minitest/autorun'
|
9
|
+
require 'nt_models'
|
10
|
+
|
11
|
+
# Define file path pattern for identifying test files:
|
12
|
+
test_pattern = '*_test.rb'
|
13
|
+
|
14
|
+
describe 'NanoTwitter' do
|
15
|
+
before do
|
16
|
+
ActiveRecord::Base.subclasses.each(&:delete_all)
|
17
|
+
names = %w[ari brad yang pito]
|
18
|
+
users = names.map { |s| User.create(name: s.capitalize, handle: "@#{s}", password: "#{s}123") }
|
19
|
+
@ari, @brad, @yang, @pito = users
|
20
|
+
end
|
21
|
+
|
22
|
+
Dir["#{__dir__}/#{test_pattern}"].each { |file| require file }
|
23
|
+
end
|
data/test/tweet_test.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
describe 'tweets' do
|
2
|
+
|
3
|
+
before do
|
4
|
+
@tweet = Tweet.create(author_id: @ari.id, body: 'Scalability!', created_on: DateTime.now)
|
5
|
+
end
|
6
|
+
|
7
|
+
it 'can create a tweet' do
|
8
|
+
Tweet.count.must_equal 1
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'can associate tweets with authors' do
|
12
|
+
@ari.tweets.count.must_equal 1
|
13
|
+
@tweet.author.must_equal @ari
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
data/test/user_test.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
describe 'User model' do
|
2
|
+
|
3
|
+
it 'has 4 users' do
|
4
|
+
User.count.must_equal 4
|
5
|
+
end
|
6
|
+
|
7
|
+
it 'can destroy a user' do
|
8
|
+
@ari.destroy
|
9
|
+
User.count.must_equal 3
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'requires a handle and a password' do
|
13
|
+
chi = User.new(name: 'Chi', password: 'chi123')
|
14
|
+
chi.save.must_equal false
|
15
|
+
|
16
|
+
chi = User.new(name: 'Chi', handle: '@chi')
|
17
|
+
chi.save.must_equal false
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'requires a unique handle' do
|
21
|
+
fake_ari = User.new(name: 'Ari', handle: @ari.handle, password: 'identitytheftisnotajoke')
|
22
|
+
fake_ari.save.must_equal false
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'can authenticate a user' do
|
26
|
+
@ari.authenticate('ari123').must_equal @ari
|
27
|
+
@ari.authenticate('iforgetmypassword').must_equal false
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
metadata
ADDED
@@ -0,0 +1,161 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: nt_models
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ari Carr
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-03-15 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activerecord
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 5.2.2
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 5.2.2
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: sinatra
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: sinatra-activerecord
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: pg
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: bcrypt
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: simplecov
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
description:
|
112
|
+
email: acarr@brandeis.edu
|
113
|
+
executables: []
|
114
|
+
extensions: []
|
115
|
+
extra_rdoc_files: []
|
116
|
+
files:
|
117
|
+
- "./db/migrate/20190225192049_create_user_table.rb"
|
118
|
+
- "./db/migrate/20190225201314_create_tweet_table.rb"
|
119
|
+
- "./db/migrate/20190226212517_create_tweet_tag_table.rb"
|
120
|
+
- "./db/migrate/20190226212626_create_hashtag_table.rb"
|
121
|
+
- "./db/migrate/20190226212645_create_timeline_piece_table.rb"
|
122
|
+
- "./db/migrate/20190226212658_create_mention_table.rb"
|
123
|
+
- "./db/migrate/20190226212737_create_follow_table.rb"
|
124
|
+
- "./db/migrate/nt_models.rb"
|
125
|
+
- "./db/schema.rb"
|
126
|
+
- "./lib/models/follow.rb"
|
127
|
+
- "./lib/models/hashtag.rb"
|
128
|
+
- "./lib/models/mention.rb"
|
129
|
+
- "./lib/models/timeline_piece.rb"
|
130
|
+
- "./lib/models/tweet.rb"
|
131
|
+
- "./lib/models/tweet_tag.rb"
|
132
|
+
- "./lib/models/user.rb"
|
133
|
+
- "./lib/nt_models.rb"
|
134
|
+
- "./test/follow_test.rb"
|
135
|
+
- "./test/test_helper.rb"
|
136
|
+
- "./test/tweet_test.rb"
|
137
|
+
- "./test/user_test.rb"
|
138
|
+
homepage:
|
139
|
+
licenses: []
|
140
|
+
metadata: {}
|
141
|
+
post_install_message:
|
142
|
+
rdoc_options: []
|
143
|
+
require_paths:
|
144
|
+
- lib
|
145
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
146
|
+
requirements:
|
147
|
+
- - ">="
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
version: '0'
|
150
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
151
|
+
requirements:
|
152
|
+
- - ">="
|
153
|
+
- !ruby/object:Gem::Version
|
154
|
+
version: '0'
|
155
|
+
requirements: []
|
156
|
+
rubyforge_project:
|
157
|
+
rubygems_version: 2.5.2
|
158
|
+
signing_key:
|
159
|
+
specification_version: 4
|
160
|
+
summary: Models for COSI 105B project
|
161
|
+
test_files: []
|