nt_models 0.1.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.
- 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: []
|