nt_models 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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,10 @@
1
+ # Initializes the db's User table
2
+ class CreateUserTable < ActiveRecord::Migration[5.2]
3
+ def change
4
+ create_table :users do |t|
5
+ t.string :name
6
+ t.string :handle
7
+ t.string :password_digest
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ # Initializes the db's Tweet table
2
+ class CreateTweetTable < ActiveRecord::Migration[5.2]
3
+ def change
4
+ create_table :tweets do |t|
5
+ t.string :body
6
+ t.datetime :created_on
7
+ t.integer :author_id
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,9 @@
1
+ # Initializes db's Tweet Tag table
2
+ class CreateTweetTagTable < ActiveRecord::Migration[5.2]
3
+ def change
4
+ create_table :tweet_tags do |t|
5
+ t.integer :hashtag_id
6
+ t.integer :tweet_id
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,8 @@
1
+ # Initializes the db's Hashtag table
2
+ class CreateHashtagTable < ActiveRecord::Migration[5.2]
3
+ def change
4
+ create_table :hashtags do |t|
5
+ t.text :name
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,9 @@
1
+ # Initializes db's Timeline Piece table
2
+ class CreateTimelinePieceTable < ActiveRecord::Migration[5.2]
3
+ def change
4
+ create_table :timeline_pieces do |t|
5
+ t.integer :timeline_owner_id
6
+ t.integer :tweet_id
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ # Initializes the db's Mention table
2
+ class CreateMentionTable < ActiveRecord::Migration[5.2]
3
+ def change
4
+ create_table :mentions do |t|
5
+ t.integer :tweet_id
6
+ t.integer :mentioned_user_id
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ # Initializes db's Follow table
2
+ class CreateFollowTable < ActiveRecord::Migration[5.2]
3
+ def change
4
+ create_table :follows do |t|
5
+ t.integer :follower_id
6
+ t.integer :followee_id
7
+ end
8
+ end
9
+ end
@@ -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
@@ -0,0 +1,5 @@
1
+ # Represents the db's Hashtag table
2
+ class Hashtag < ActiveRecord::Base
3
+ has_many :tweet_tags
4
+ has_many :tweets, through: :tweet_tags
5
+ end
@@ -0,0 +1,5 @@
1
+ # Represents the db's Mention table
2
+ class Mention < ActiveRecord::Base
3
+ belongs_to :mentioned_user, class_name: 'User'
4
+ belongs_to :tweet
5
+ end
@@ -0,0 +1,5 @@
1
+ # Represents the db's Timeline_piece table
2
+ class TimelinePiece < ActiveRecord::Base
3
+ belongs_to :timeline_owner
4
+ belongs_to :tweet
5
+ end
@@ -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
@@ -0,0 +1,5 @@
1
+ # Represents the db's Tweet_Tag table
2
+ class TweetTag < ActiveRecord::Base
3
+ belongs_to :tweet
4
+ belongs_to :hashtag
5
+ end
@@ -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
@@ -0,0 +1,8 @@
1
+ require 'sinatra/activerecord'
2
+ require 'active_record'
3
+
4
+ unless Sinatra::Base.production?
5
+ require 'pry-byebug'
6
+ end
7
+
8
+ Dir["#{__dir__}/models/*.rb"].each { |file| require file }
@@ -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
@@ -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
@@ -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: []