Commit 3f81f3b1 by Son Do Hong

Merge branch 'user-microposts' into 'master'

User microposts

See merge request !13
parents 6c0ca261 26f9ddef
......@@ -21,3 +21,6 @@
/yarn-error.log
.byebug_history
# Ignore uploaded test images.
/public/uploads
......@@ -3,6 +3,8 @@ source "https://rubygems.org"
gem "rails", "5.1.6"
gem "bcrypt", "3.1.12"
gem "faker", "1.7.3"
gem "carrierwave", "1.2.2"
gem "mini_magick", "4.7.0"
gem "will_paginate", "3.1.6"
gem "bootstrap-will_paginate", "1.0.0"
gem "bootstrap-sass", "3.3.7"
......@@ -36,6 +38,7 @@ end
group :production do
gem "pg", "0.20.0"
gem "fog", "1.42"
end
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
......
GEM
remote: https://rubygems.org/
specs:
CFPropertyList (2.3.6)
actioncable (5.1.6)
actionpack (= 5.1.6)
nio4r (~> 2.0)
......@@ -51,6 +52,10 @@ GEM
will_paginate
builder (3.2.3)
byebug (9.0.6)
carrierwave (1.2.2)
activemodel (>= 4.0.0)
activesupport (>= 4.0.0)
mime-types (>= 1.16)
coderay (1.1.2)
coffee-rails (4.2.2)
coffee-script (>= 2.2.0)
......@@ -61,11 +66,171 @@ GEM
coffee-script-source (1.12.2)
concurrent-ruby (1.1.5)
crass (1.0.5)
domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0)
dry-inflector (0.2.0)
erubi (1.9.0)
excon (0.68.0)
execjs (2.7.0)
faker (1.7.3)
i18n (~> 0.5)
ffi (1.11.2)
fission (0.5.0)
CFPropertyList (~> 2.2)
fog (1.42.0)
fog-aliyun (>= 0.1.0)
fog-atmos
fog-aws (>= 0.6.0)
fog-brightbox (~> 0.4)
fog-cloudatcost (~> 0.1.0)
fog-core (~> 1.45)
fog-digitalocean (>= 0.3.0)
fog-dnsimple (~> 1.0)
fog-dynect (~> 0.0.2)
fog-ecloud (~> 0.1)
fog-google (<= 0.1.0)
fog-internet-archive
fog-joyent
fog-json
fog-local
fog-openstack
fog-ovirt
fog-powerdns (>= 0.1.1)
fog-profitbricks
fog-rackspace
fog-radosgw (>= 0.0.2)
fog-riakcs
fog-sakuracloud (>= 0.0.4)
fog-serverlove
fog-softlayer
fog-storm_on_demand
fog-terremark
fog-vmfusion
fog-voxel
fog-vsphere (>= 0.4.0)
fog-xenserver
fog-xml (~> 0.1.1)
ipaddress (~> 0.5)
json (~> 2.0)
fog-aliyun (0.3.5)
fog-core
fog-json
ipaddress (~> 0.8)
xml-simple (~> 1.1)
fog-atmos (0.1.0)
fog-core
fog-xml
fog-aws (2.0.1)
fog-core (~> 1.38)
fog-json (~> 1.0)
fog-xml (~> 0.1)
ipaddress (~> 0.8)
fog-brightbox (0.16.1)
dry-inflector
fog-core
fog-json
mime-types
fog-cloudatcost (0.1.2)
fog-core (~> 1.36)
fog-json (~> 1.0)
fog-xml (~> 0.1)
ipaddress (~> 0.8)
fog-core (1.45.0)
builder
excon (~> 0.58)
formatador (~> 0.2)
fog-digitalocean (0.4.0)
fog-core
fog-json
fog-xml
ipaddress (>= 0.5)
fog-dnsimple (1.0.0)
fog-core (~> 1.38)
fog-json (~> 1.0)
fog-dynect (0.0.3)
fog-core
fog-json
fog-xml
fog-ecloud (0.3.0)
fog-core
fog-xml
fog-google (0.1.0)
fog-core
fog-json
fog-xml
fog-internet-archive (0.0.1)
fog-core
fog-json
fog-xml
fog-joyent (0.0.1)
fog-core (~> 1.42)
fog-json (>= 1.0)
fog-json (1.2.0)
fog-core
multi_json (~> 1.10)
fog-local (0.6.0)
fog-core (>= 1.27, < 3.0)
fog-openstack (0.3.10)
fog-core (>= 1.45, <= 2.1.0)
fog-json (>= 1.0)
ipaddress (>= 0.8)
fog-ovirt (1.2.2)
fog-core
fog-json
fog-xml
ovirt-engine-sdk (>= 4.1.3)
rbovirt (~> 0.1.5)
fog-powerdns (0.2.0)
fog-core
fog-json
fog-xml
fog-profitbricks (4.1.1)
fog-core (~> 1.42)
fog-json (~> 1.0)
fog-rackspace (0.1.6)
fog-core (>= 1.35)
fog-json (>= 1.0)
fog-xml (>= 0.1)
ipaddress (>= 0.8)
fog-radosgw (0.0.5)
fog-core (>= 1.21.0)
fog-json
fog-xml (>= 0.0.1)
fog-riakcs (0.1.0)
fog-core
fog-json
fog-xml
fog-sakuracloud (1.7.5)
fog-core
fog-json
fog-serverlove (0.1.2)
fog-core
fog-json
fog-softlayer (1.1.4)
fog-core
fog-json
fog-storm_on_demand (0.1.1)
fog-core
fog-json
fog-terremark (0.1.0)
fog-core
fog-xml
fog-vmfusion (0.1.0)
fission
fog-core
fog-voxel (0.1.0)
fog-core
fog-xml
fog-vsphere (3.2.1)
fog-core
rbvmomi (>= 1.9, < 3)
fog-xenserver (1.0.0)
fog-core
fog-xml
xmlrpc
fog-xml (0.1.3)
fog-core
nokogiri (>= 1.5.11, < 2.0.0)
formatador (0.2.5)
globalid (0.4.2)
activesupport (>= 4.2.0)
......@@ -82,8 +247,12 @@ GEM
guard-minitest (2.4.4)
guard-compat (~> 1.2)
minitest (>= 3.0)
http-accept (1.7.0)
http-cookie (1.0.3)
domain_name (~> 0.5)
i18n (0.9.5)
concurrent-ruby (~> 1.0)
ipaddress (0.8.3)
jbuilder (2.7.0)
activesupport (>= 4.2.0)
multi_json (>= 1.2)
......@@ -91,6 +260,7 @@ GEM
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
json (2.2.0)
listen (3.1.5)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
......@@ -102,6 +272,10 @@ GEM
mail (2.7.1)
mini_mime (>= 0.1.1)
method_source (0.9.2)
mime-types (3.3)
mime-types-data (~> 3.2015)
mime-types-data (3.2019.1009)
mini_magick (4.7.0)
mini_mime (1.0.2)
mini_portile2 (2.4.0)
minitest (5.10.3)
......@@ -112,12 +286,16 @@ GEM
ruby-progressbar
multi_json (1.14.1)
nenv (0.3.0)
netrc (0.11.0)
nio4r (2.5.2)
nokogiri (1.10.5)
mini_portile2 (~> 2.4.0)
notiffany (0.1.3)
nenv (~> 0.1)
shellany (~> 0.0)
optimist (3.0.0)
ovirt-engine-sdk (4.3.0)
json (>= 1, < 3)
pg (0.20.0)
pry (0.12.2)
coderay (~> 1.1.0)
......@@ -157,6 +335,19 @@ GEM
rb-fsevent (0.10.3)
rb-inotify (0.10.0)
ffi (~> 1.0)
rbovirt (0.1.7)
nokogiri
rest-client (> 1.7.0)
rbvmomi (2.2.0)
builder (~> 3.0)
json (>= 1.8)
nokogiri (~> 1.5)
optimist (~> 3.0)
rest-client (2.1.0)
http-accept (>= 1.7.0, < 2.0)
http-cookie (>= 1.0.2, < 2.0)
mime-types (>= 1.16, < 4.0)
netrc (~> 0.8)
ruby-progressbar (1.10.1)
ruby_dep (1.5.0)
sass (3.7.4)
......@@ -194,6 +385,9 @@ GEM
thread_safe (~> 0.1)
uglifier (3.2.0)
execjs (>= 0.3.0, < 3)
unf (0.1.4)
unf_ext
unf_ext (0.0.7.6)
web-console (3.5.1)
actionview (>= 5.0)
activemodel (>= 5.0)
......@@ -203,6 +397,8 @@ GEM
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.4)
will_paginate (3.1.6)
xml-simple (1.1.5)
xmlrpc (0.3.0)
PLATFORMS
ruby
......@@ -212,13 +408,16 @@ DEPENDENCIES
bootstrap-sass (= 3.3.7)
bootstrap-will_paginate (= 1.0.0)
byebug (= 9.0.6)
carrierwave (= 1.2.2)
coffee-rails (= 4.2.2)
faker (= 1.7.3)
fog (= 1.42)
guard (= 2.13.0)
guard-minitest (= 2.4.4)
jbuilder (= 2.7.0)
jquery-rails (= 4.3.1)
listen (= 3.1.5)
mini_magick (= 4.7.0)
minitest (= 5.10.3)
minitest-reporters (= 1.1.14)
pg (= 0.20.0)
......
......@@ -202,3 +202,50 @@ input {
border-bottom: 1px solid $gray-lighter;
}
}
/* microposts */
.microposts {
list-style: none;
padding: 0;
li {
padding: 10px 0;
border-top: 1px solid #e8e8e8;
}
.user {
margin-top: 5em;
padding-top: 0;
}
.content {
display: block;
margin-left: 60px;
img {
display: block;
padding: 5px 0;
}
}
.timestamp {
color: $gray-light;
display: block;
margin-left: 60px;
}
.gravatar {
float: left;
margin-right: 10px;
margin-top: 5px;
}
}
aside {
textarea {
height: 100px;
margin-bottom: 5px;
}
}
span.picture {
margin-top: 10px;
input {
border: 0;
}
}
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
include SessionsHelper
private
# Confirms a logged-in user.
def logged_in_user
unless logged_in?
store_location
flash[:danger] = "Please log in."
redirect_to login_url
end
end
end
class MicropostsController < ApplicationController
before_action :logged_in_user, only: [:create, :destroy]
before_action :correct_user, only: :destroy
def create
@micropost = current_user.microposts.build(micropost_params)
if @micropost.save
flash[:success] = "Micropost created!"
redirect_to root_url
else
@feed_items = []
render "static_pages/home"
end
end
def destroy
@micropost.destroy
flash[:success] = "Micropost deleted"
redirect_to request.referrer || root_url
end
private
def micropost_params
params.require(:micropost).permit(:content, :picture)
end
def correct_user
@micropost = current_user.microposts.find_by(id: params[:id])
redirect_to root_url if @micropost.nil?
end
end
class StaticPagesController < ApplicationController
def home
if logged_in?
@micropost = current_user.microposts.build
@feed_items = current_user.feed.paginate(page: params[:page])
end
end
def help
......
......@@ -10,6 +10,7 @@ class UsersController < ApplicationController
def show
@user = User.find(params[:id])
redirect_to root_url and return unless @user.activated
@microposts = @user.microposts.paginate(page: params[:page])
end
def new
......@@ -57,20 +58,14 @@ class UsersController < ApplicationController
params.require(:user).permit(:name, :email, :password, :password_confirmation)
end
# Before filters
# Confirms a logged-in user.
def logged_in_user
unless logged_in?
store_location
flash[:danger] = "Please log in."
redirect_to login_url
end
end
# Confirms the correct user.
def correct_user
@user = User.find(params[:id])
redirect_to(root_url) unless current_user?(@user)
end
# Confirms an admin user.
def admin_user
redirect_to(root_url) unless current_user.admin?
end
end
module ApplicationHelper
# Returns the full title on a per-page basis.
def full_title(page_title = '')
def full_title(page_title = "")
base_title = "Ruby on Rails Tutorial Sample App"
if page_title.empty?
base_title
......
class Micropost < ApplicationRecord
default_scope -> { order(created_at: :desc) }
mount_uploader :picture, PictureUploader
belongs_to :user
validates :user_id, presence: true
validates :content, presence: true, length: { maximum: 140 }
validate :picture_size
private
# Validates the size of an uploaded picture.
def picture_size
if picture.size > 5.megabytes
errors.add(:picture, "should be less than 5MB")
end
end
end
......@@ -3,6 +3,8 @@ class User < ApplicationRecord
attr_accessor :remember_token, :activation_token, :reset_token
has_many :microposts, dependent: :destroy
validates :email, presence: true, length: { maximum: 255 }, format: { with: VALID_EMAIL_REGEX }, uniqueness: { case_sensitive: false }
validates :name, presence: true, length: { maximum: 50 }
validates :password, presence: true, length: { minimum: 6 }, allow_nil: true
......@@ -76,6 +78,12 @@ class User < ApplicationRecord
reset_sent_at < 2.hours.ago
end
# Defines a proto-feed.
# See "Following users" for the full implementation.
def feed
Micropost.where("user_id = ?", id)
end
private
# Converts email to all lower-case.
......
class PictureUploader < CarrierWave::Uploader::Base
# Include RMagick or MiniMagick support:
# include CarrierWave::RMagick
# include CarrierWave::MiniMagick
include CarrierWave::MiniMagick
process resize_to_limit: [400, 400]
if Rails.env.production?
storage :fog
else
storage :file
end
# Override the directory where uploaded files will be stored.
# This is a sensible default for uploaders that are meant to be mounted:
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
# Provide a default URL as a default if there hasn't been a file uploaded:
# def default_url(*args)
# # For Rails 3.1+ asset pipeline compatibility:
# # ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_'))
#
# "/images/fallback/" + [version_name, "default.png"].compact.join('_')
# end
# Process files as they are uploaded:
# process scale: [200, 300]
#
# def scale(width, height)
# # do something
# end
# Create different versions of your uploaded files:
# version :thumb do
# process resize_to_fit: [50, 50]
# end
# Add a white list of extensions which are allowed to be uploaded.
# For images you might use something like this:
# def extension_whitelist
# %w(jpg jpeg gif png)
# end
# Override the filename of the uploaded files:
# Avoid using model.id or version_name here, see uploader/store.rb for details.
# def filename
# "something.jpg" if original_filename
# end
# Add a white list of extensions which are allowed to be uploaded.
def extension_whitelist
%w(jpg jpeg gif png)
end
end
<li id="micropost-<%= micropost.id %>">
<%= link_to gravatar_for(micropost.user, size: 50), micropost.user %>
<span class="user"><%= link_to micropost.user.name, micropost.user %></span>
<span class="content">
<%= micropost.content %>
<%= image_tag micropost.picture.url if micropost.picture? %>
</span>
<span class="timestamp">
Posted <%= time_ago_in_words(micropost.created_at) %> ago.
<% if current_user?(micropost.user) %>
<%= link_to "delete", micropost, method: :delete, data: { confirm: "You sure?" } %>
<% end %>
</span>
</li>
<% provide(:title, "Reset password") %>
<h1>Reset password</h1>
<h1>Password reset</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for(@user, url: password_reset_path(params[:id])) do |f| %>
<%= render "shared/error_messages" %>
<%= render "shared/error_messages", object: f.object %>
<%= hidden_field_tag :email, @user.email %>
<%= f.label :password %>
<%= f.password_field :password, class: "form-control" %>
<%= f.label :password_confirmation, "Confirmation" %>
<%= f.password_field :password_confirmation, class: "form-control" %>
<%= f.submit "Update password", class: "btn btn-primary" %>
<% end %>
</div>
......
<% if @user.errors.any? %>
<% if object.errors.any? %>
<div id="error_explanation">
<div class="alert alert-danger">
The form contains <%= pluralize(@user.errors.count, "error") %>.
The form contains <%= pluralize(object.errors.count, "error") %>.
</div>
<ul>
<% @user.errors.full_messages.each do |msg| %>
<% object.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
......
<% if @feed_items.any? %>
<ol class="microposts">
<%= render @feed_items %>
</ol>
<%= will_paginate @feed_items %>
<% end %>
<%= form_for(@micropost) do |f| %>
<%= render "shared/error_messages", object: f.object %>
<div class="field">
<%= f.text_area :content, placeholder: "Compose new micropost..." %>
</div>
<%= f.submit "Post", class: "btn btn-primary" %>
<span class="picture">
<%= f.file_field :picture, accept: "image/jpeg,image/gif,image/png" %>
</span>
<% end %>
<script type="text/javascript">
$("#micropost_picture").bind("change", function() {
var size_in_megabytes = this.files[0].size/1024/1024;
if (size_in_megabytes > 5) {
alert("Maximum file size is 5MB. Please choose a smaller file.");
}
});
</script>
<%= link_to gravatar_for(current_user, size: 50), current_user %>
<h1><%= current_user.name %></h1>
<span><%= link_to "view my profile", current_user %></span>
<span><%= pluralize(current_user.microposts.count, "micropost") %></span>
<div class="center jumbotron">
<% if logged_in? %>
<div class="row">
<aside class="col-md-4">
<section class="user_info">
<%= render "shared/user_info" %>
</section>
<section class="micropost_form">
<%= render "shared/micropost_form" %>
</section>
</aside>
<div class="col-md-8">
<h3>Micropost Feed</h3>
<%= render "shared/feed" %>
</div>
</div>
<% else %>
<div class="center jumbotron">
<h1>Welcome to the Sample App</h1>
<h2>
......@@ -8,6 +24,7 @@
</h2>
<%= link_to "Sign up now!", signup_path, class: "btn btn-lg btn-primary" %>
</div>
</div>
<%= link_to image_tag("rails.png", alt: "Rails logo"),"http://rubyonrails.org/" %>
<% end %>
<% provide(:title, "Edit user") %>
<% provide(:button_text, "Save changes") %>
<h1>Update your profile</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= render "form" %>
<div class="gravatar_edit">
<%= gravatar_for @user %>
<a href="http://gravatar.com/emails" target="_blank">Change</a>
<a href="http://gravatar.com/emails">change</a>
</div>
</div>
</div>
<% provide(:title, "Sign up") %>
<% provide(:button_text, "Create my account") %>
<h1>Sign up</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= render "form" %>
......
......@@ -8,4 +8,13 @@
</h1>
</section>
</aside>
<div class="col-md-8">
<% if @user.microposts.any? %>
<h3>Microposts (<%= @user.microposts.count %>)</h3>
<ol class="microposts">
<%= render @microposts %>
</ol>
<%= will_paginate @microposts %>
<% end %>
</div>
</div>
#!/usr/bin/env ruby
begin
load File.expand_path('../spring', __FILE__)
load File.expand_path("../spring", __FILE__)
rescue LoadError => e
raise unless e.message.include?('spring')
raise unless e.message.include?("spring")
end
require_relative '../config/boot'
require 'rake'
require_relative "../config/boot"
require "rake"
Rake.application.run
# Load the Rails application.
require_relative 'application'
require_relative "application"
# Initialize the Rails application.
Rails.application.initialize!
......@@ -54,4 +54,7 @@ Rails.application.configure do
# Use an evented file watcher to asynchronously detect changes in source code,
# routes, locales, etc. This feature depends on the listen gem.
config.file_watcher = ActiveSupport::EventedFileUpdateChecker
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = { :address => "localhost", :port => 1025 }
end
# Be sure to restart your server when you modify this file.
# Version of your assets, change this if you want to expire all your assets.
Rails.application.config.assets.version = '1.0'
Rails.application.config.assets.version = "1.0"
# Add additional assets to the asset load path.
# Rails.application.config.assets.paths << Emoji.images_path
# Add Yarn node_modules folder to the asset load path.
Rails.application.config.assets.paths << Rails.root.join('node_modules')
Rails.application.config.assets.paths << Rails.root.join("node_modules")
# Precompile additional assets.
# application.js, application.css, and all non-JS/CSS in the app/assets
......
if Rails.env.production?
CarrierWave.configure do |config|
config.fog_credentials = {
# Configuration for Amazon S3
:provider => "AWS",
:aws_access_key_id => ENV["S3_ACCESS_KEY"],
:aws_secret_access_key => ENV["S3_SECRET_KEY"]
}
config.fog_directory = ENV["S3_BUCKET"]
end
end
if Rails.env.test?
CarrierWave.configure do |config|
config.enable_processing = false
end
end
......@@ -12,4 +12,5 @@ Rails.application.routes.draw do
resources :users
resources :account_activations, only: [:edit]
resources :password_resets, only: [:new, :create, :edit, :update]
resources :microposts, only: [:create, :destroy]
end
class CreateMicroposts < ActiveRecord::Migration[5.1]
def change
create_table :microposts do |t|
t.text :content
t.references :user, foreign_key: true
t.timestamps
end
add_index :microposts, [:user_id, :created_at]
end
end
class AddPictureToMicroposts < ActiveRecord::Migration[5.1]
def change
add_column :microposts, :picture, :string
end
end
......@@ -6,11 +6,21 @@
# database schema. If you need to create the application database on another
# system, you should be using db:schema:load, not running all the migrations
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
# you'll amass, the slower it'll run and the greater likelihood for issues).
# you"ll amass, the slower it"ll run and the greater likelihood for issues).
#
# It's strongly recommended that you check this file into your version control system.
# It"s strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20191120021439) do
ActiveRecord::Schema.define(version: 20191120093834) do
create_table "microposts", force: :cascade do |t|
t.text "content"
t.integer "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "picture"
t.index ["user_id", "created_at"], name: "index_microposts_on_user_id_and_created_at"
t.index ["user_id"], name: "index_microposts_on_user_id"
end
create_table "users", force: :cascade do |t|
t.string "name"
......
......@@ -17,3 +17,9 @@ User.create!(name: "Example User",
activated: true,
activated_at: Time.current)
end
users = User.order(:created_at).take(6)
50.times do
content = Faker::Lorem.sentence(5)
users.each { |user| user.microposts.create!(content: content) }
end
require "test_helper"
class MicropostsControllerTest < ActionDispatch::IntegrationTest
def setup
@micropost = microposts(:orange)
end
test "should redirect create when not logged in" do
assert_no_difference "Micropost.count" do
post microposts_path, params: { micropost: { content: "Lorem ipsum" } }
end
assert_redirected_to login_url
end
test "should redirect destroy when not logged in" do
assert_no_difference "Micropost.count" do
delete micropost_path(@micropost)
end
assert_redirected_to login_url
end
test "should redirect destroy for wrong micropost" do
log_in_as(users(:michael))
micropost = microposts(:ants)
assert_no_difference "Micropost.count" do
delete micropost_path(micropost)
end
assert_redirected_to root_url
end
end
orange:
content: "I just ate an orange!"
created_at: <%= 10.minutes.ago %>
user: michael
tau_manifesto:
content: "Check out the @tauday site by @mhartl: http://tauday.com"
created_at: <%= 3.years.ago %>
user: michael
cat_video:
content: "Sad cats are sad: http://youtu.be/PKffm2uI4dk"
created_at: <%= 2.hours.ago %>
user: michael
most_recent:
content: "Writing a short test"
created_at: <%= Time.zone.now %>
user: michael
<% 30.times do |n| %>
micropost_<%= n %>:
content: <%= Faker::Lorem.sentence(5) %>
created_at: <%= 42.days.ago %>
user: michael
<% end %>
ants:
content: "Oh, is that what you want? Because that's how you get ants!"
created_at: <%= 2.years.ago %>
user: archer
zone:
content: "Danger zone!"
created_at: <%= 3.days.ago %>
user: archer
tone:
content: "I'm sorry. Your words made sense, but your sarcastic tone did not."
created_at: <%= 10.minutes.ago %>
user: lana
van:
content: "Dude, this van's, like, rolling probable cause."
created_at: <%= 4.hours.ago %>
user: lana
require "test_helper"
class MicropostInterfaceTest < ActionDispatch::IntegrationTest
def setup
@user = users(:michael)
end
test "micropost interface" do
log_in_as(@user)
get root_path
assert_select "div.pagination"
assert_select "input[type=file]"
# Invalid submission
assert_no_difference "Micropost.count" do
post microposts_path, params: { micropost: { content: "" } }
end
assert_select "div#error_explanation"
# Valid submission
content = "This micropost really ties the room together"
picture = fixture_file_upload("app/assets/images/rails.png", "image/png")
assert_difference "Micropost.count", 1 do
post microposts_path, params: { micropost: { content: content, picture: picture } }
end
micropost = assigns(:micropost)
assert micropost.picture?
assert_redirected_to root_url
follow_redirect!
assert_match content, response.body
# Delete post
assert_select "a", text: "delete"
first_micropost = @user.microposts.paginate(page: 1).first
assert_difference "Micropost.count", -1 do
delete micropost_path(first_micropost)
end
# Visit different user (no delete links)
get user_path(users(:archer))
assert_select "a", text: "delete", count: 0
end
end
require "test_helper"
class UsersProfileTest < ActionDispatch::IntegrationTest
include ApplicationHelper
def setup
@user = users(:michael)
end
test "profile display" do
get user_path(@user)
assert_template "users/show"
assert_select "title", full_title(@user.name)
assert_select "h1", text: @user.name
assert_select "h1>img.gravatar"
assert_match @user.microposts.count.to_s, response.body
assert_select "div.pagination"
@user.microposts.paginate(page: 1).each do |micropost|
assert_match micropost.content, response.body
end
end
end
require "test_helper"
class MicropostTest < ActiveSupport::TestCase
def setup
@user = users(:michael)
@micropost = @user.microposts.build(content: "Lorem ipsum")
end
test "should be valid" do
assert @micropost.valid?
end
test "user id should be present" do
@micropost.user_id = nil
assert_not @micropost.valid?
end
test "content should be present" do
@micropost.content = " "
assert_not @micropost.valid?
end
test "content should be at most 140 characters" do
@micropost.content = "a" * 141
assert_not @micropost.valid?
end
test "order should be most recent first" do
assert_equal microposts(:most_recent), Micropost.first
end
end
......@@ -72,6 +72,14 @@ class UserTest < ActiveSupport::TestCase
end
test "authenticated? should return false for a user with nil digest" do
assert_not @user.authenticated?(:remember, '')
assert_not @user.authenticated?(:remember, "")
end
test "associated microposts should be destroyed" do
@user.save
@user.microposts.create!(content: "Lorem ipsum")
assert_difference "Micropost.count", -1 do
@user.destroy
end
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