diff --git a/Gemfile b/Gemfile index c1f1ee3e2..6f0abe0d3 100644 --- a/Gemfile +++ b/Gemfile @@ -5,19 +5,10 @@ git_source(:github) do |repo_name| "https://github.com/#{repo_name}.git" end -# user authentication -gem 'devise' -# file uploader -gem 'carrierwave' -# resize image size -# gem 'mini_magick' - -gem 'ffaker' # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' -gem 'rails', '~> 5.1.4' -# Use sqlite3 as the database for Active Record -gem 'sqlite3' +gem 'rails', '~> 5.1.6' + # Use Puma as the app server gem 'puma', '~> 3.7' # Use SCSS for stylesheets @@ -34,13 +25,28 @@ gem 'turbolinks', '~> 5' # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder gem 'jbuilder', '~> 2.5' # Use Redis adapter to run Action Cable in production -# gem 'redis', '~> 3.0' +# gem 'redis', '~> 4.0' # Use ActiveModel has_secure_password # gem 'bcrypt', '~> 3.1.7' # Use Capistrano for deployment # gem 'capistrano-rails', group: :development +#for User +gem 'devise' +#for image +gem 'carrierwave' +#for fake data +gem 'ffaker' +# Use uinames +gem 'rest-client' + +gem 'kaminari' +gem 'bootstrap-sass', '~> 3.3.7' +gem 'jquery-rails' + +gem 'fog-aws' + group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] @@ -51,6 +57,7 @@ group :development, :test do gem 'factory_bot_rails' gem 'shoulda-matchers', '~> 3.1' gem 'rails-controller-testing' + gem 'sqlite3' end group :development do @@ -62,5 +69,9 @@ group :development do gem 'spring-watcher-listen', '~> 2.0.0' end +group :production do + gem 'pg', '~> 0.20' +end + # Windows does not include zoneinfo files, so bundle the tzinfo-data gem gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby] diff --git a/Gemfile.lock b/Gemfile.lock index 3b212e9b7..9546e43e6 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -41,11 +41,13 @@ GEM addressable (2.5.2) public_suffix (>= 2.0.2, < 4.0) arel (8.0.0) + autoprefixer-rails (8.5.0) + execjs bcrypt (3.1.12) - bcrypt (3.1.12-java) - bcrypt (3.1.12-x64-mingw32) - bcrypt (3.1.12-x86-mingw32) bindex (0.5.0) + bootstrap-sass (3.3.7) + autoprefixer-rails (>= 5.2.1) + sass (>= 3.3.4) builder (3.2.3) byebug (10.0.2) capybara (2.18.0) @@ -69,7 +71,6 @@ GEM execjs coffee-script-source (1.12.2) concurrent-ruby (1.0.5) - concurrent-ruby (1.0.5-java) crass (1.0.4) devise (4.4.3) bcrypt (~> 3.0) @@ -78,7 +79,10 @@ GEM responders warden (~> 1.2.3) diff-lcs (1.3) + domain_name (0.5.20180417) + unf (>= 0.0.5, < 1.0.0) erubi (1.7.1) + excon (0.62.0) execjs (2.7.0) factory_bot (4.10.0) activesupport (>= 3.0.0) @@ -87,16 +91,49 @@ GEM railties (>= 3.0.0) ffaker (2.10.0) ffi (1.9.25) - ffi (1.9.25-java) - ffi (1.9.25-x64-mingw32) - ffi (1.9.25-x86-mingw32) + fog-aws (3.0.0) + fog-core (~> 2.1) + fog-json (~> 1.1) + fog-xml (~> 0.1) + ipaddress (~> 0.8) + fog-core (2.1.0) + builder + excon (~> 0.58) + formatador (~> 0.2) + mime-types + fog-json (1.2.0) + fog-core + multi_json (~> 1.10) + fog-xml (0.1.3) + fog-core + nokogiri (>= 1.5.11, < 2.0.0) + formatador (0.2.5) globalid (0.4.1) activesupport (>= 4.2.0) + http-cookie (1.0.3) + domain_name (~> 0.5) i18n (1.0.1) concurrent-ruby (~> 1.0) + ipaddress (0.8.3) jbuilder (2.7.0) activesupport (>= 4.2.0) multi_json (>= 1.2) + jquery-rails (4.3.3) + rails-dom-testing (>= 1, < 3) + railties (>= 4.2.0) + thor (>= 0.14, < 2.0) + kaminari (1.1.1) + activesupport (>= 4.1.0) + kaminari-actionview (= 1.1.1) + kaminari-activerecord (= 1.1.1) + kaminari-core (= 1.1.1) + kaminari-actionview (1.1.1) + actionview + kaminari-core (= 1.1.1) + kaminari-activerecord (1.1.1) + activerecord + kaminari-core (= 1.1.1) + kaminari-core (1.1.1) listen (3.1.5) rb-fsevent (~> 0.9, >= 0.9.4) rb-inotify (~> 0.9, >= 0.9.7) @@ -114,19 +151,14 @@ GEM mini_portile2 (2.3.0) minitest (5.11.3) multi_json (1.13.1) + netrc (0.11.0) nio4r (2.3.1) - nio4r (2.3.1-java) nokogiri (1.8.4) mini_portile2 (~> 2.3.0) - nokogiri (1.8.4-java) - nokogiri (1.8.4-x64-mingw32) - mini_portile2 (~> 2.3.0) - nokogiri (1.8.4-x86-mingw32) - mini_portile2 (~> 2.3.0) orm_adapter (0.5.0) + pg (0.21.0) public_suffix (3.0.2) puma (3.12.0) - puma (3.12.0-java) rack (2.0.5) rack-test (1.1.0) rack (>= 1.0, < 3) @@ -164,6 +196,10 @@ GEM responders (2.4.0) actionpack (>= 4.2.0, < 5.3) railties (>= 4.2.0, < 5.3) + rest-client (2.0.2) + http-cookie (>= 1.0.2, < 2.0) + mime-types (>= 1.16, < 4.0) + netrc (~> 0.8) rspec-core (3.7.1) rspec-support (~> 3.7.0) rspec-expectations (3.7.0) @@ -212,22 +248,19 @@ GEM activesupport (>= 4.0) sprockets (>= 3.0.0) sqlite3 (1.3.13) - sqlite3 (1.3.13-x64-mingw32) - sqlite3 (1.3.13-x86-mingw32) - sqlite3 (1.3.13-x86-mswin32-60) thor (0.20.0) thread_safe (0.3.6) - thread_safe (0.3.6-java) tilt (2.0.8) turbolinks (5.1.1) turbolinks-source (~> 5.1) turbolinks-source (5.1.0) tzinfo (1.2.5) thread_safe (~> 0.1) - tzinfo-data (1.2018.5) - tzinfo (>= 1.0.0) uglifier (4.1.17) execjs (>= 0.3.0, < 3) + unf (0.1.4) + unf_ext + unf_ext (0.0.7.5) warden (1.2.7) rack (>= 1.0) web-console (3.6.2) @@ -237,20 +270,15 @@ GEM railties (>= 5.0) websocket-driver (0.6.5) websocket-extensions (>= 0.1.0) - websocket-driver (0.6.5-java) - websocket-extensions (>= 0.1.0) websocket-extensions (0.1.3) xpath (3.1.0) nokogiri (~> 1.8) PLATFORMS - java ruby - x64-mingw32 - x86-mingw32 - x86-mswin32 DEPENDENCIES + bootstrap-sass (~> 3.3.7) byebug capybara (~> 2.13) carrierwave @@ -258,11 +286,16 @@ DEPENDENCIES devise factory_bot_rails ffaker + fog-aws jbuilder (~> 2.5) + jquery-rails + kaminari listen (>= 3.0.5, < 3.2) + pg (~> 0.20) puma (~> 3.7) - rails (~> 5.1.4) + rails (~> 5.1.6) rails-controller-testing + rest-client rspec-rails (~> 3.7) sass-rails (~> 5.0) selenium-webdriver diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 46b20359f..8e7956cfb 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -13,3 +13,6 @@ //= require rails-ujs //= require turbolinks //= require_tree . + +//= require jquery +//= require bootstrap-sprockets diff --git a/app/assets/stylesheets/admin/tweets.scss b/app/assets/stylesheets/admin/tweets.scss index 9ec2a3732..90bc7343b 100644 --- a/app/assets/stylesheets/admin/tweets.scss +++ b/app/assets/stylesheets/admin/tweets.scss @@ -1,3 +1,7 @@ +<<<<<<< HEAD // Place all the styles related to the admin/tweets controller here. +======= +// Place all the styles related to the admin::tweets controller here. +>>>>>>> be397184eefc7ef5727e1b450016174fa9246195 // They will automatically be included in application.css. // You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/assets/stylesheets/admin/users.scss b/app/assets/stylesheets/admin/users.scss index 925e31223..9d905c1bd 100644 --- a/app/assets/stylesheets/admin/users.scss +++ b/app/assets/stylesheets/admin/users.scss @@ -1,3 +1,7 @@ +<<<<<<< HEAD // Place all the styles related to the admin/users controller here. +======= +// Place all the styles related to the admin::users controller here. +>>>>>>> be397184eefc7ef5727e1b450016174fa9246195 // They will automatically be included in application.css. // You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.scss similarity index 90% rename from app/assets/stylesheets/application.css rename to app/assets/stylesheets/application.scss index d05ea0f51..9134ab518 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.scss @@ -10,6 +10,9 @@ * files in this directory. Styles in this file should be added after the last require_* statement. * It is generally better to create a new file per style scope. * - *= require_tree . - *= require_self + */ + + @import "bootstrap-sprockets"; + @import "bootstrap"; + @import "style"; \ No newline at end of file diff --git a/app/assets/stylesheets/style.scss b/app/assets/stylesheets/style.scss new file mode 100644 index 000000000..251469c55 --- /dev/null +++ b/app/assets/stylesheets/style.scss @@ -0,0 +1,30 @@ +body { + margin-top: 70px; +} + +.tweet-item { + border: 1px solid #ddd; + border-radius: 4px; + padding: 10px; + margin-bottom: 20px; +} + +.popu-item { + border: 1px solid #ddd; + border-radius: 4px; + padding: 10px; + margin-bottom: 20px; +} + +.user-item { + border: 1px solid #ddd; + border-radius: 4px; + padding: 10px; + margin: 20px ; + height: 250px; +} + +.follow-button { + margin-top: 10px; + text-align: right; +} \ No newline at end of file diff --git a/app/controllers/admin/base_controller.rb b/app/controllers/admin/base_controller.rb index 4a89583f5..741ebd19b 100644 --- a/app/controllers/admin/base_controller.rb +++ b/app/controllers/admin/base_controller.rb @@ -1,3 +1,15 @@ class Admin::BaseController < ApplicationController + before_action :authenticate_admin + + private + + def authenticate_admin + unless current_user.admin? + flash[:alert] = "非工作人員請勿進入!" + redirect_to root_path + end + end end + + diff --git a/app/controllers/admin/tweets_controller.rb b/app/controllers/admin/tweets_controller.rb index 24a57566c..5952f0f6e 100644 --- a/app/controllers/admin/tweets_controller.rb +++ b/app/controllers/admin/tweets_controller.rb @@ -1,7 +1,20 @@ class Admin::TweetsController < Admin::BaseController + def index + @tweets = Tweet.order(created_at: :desc).page(params[:page]).per(10) end def destroy + @tweet = Tweet.find(params[:id]) + + if current_user.admin? + @tweet.destroy + redirect_to admin_root_path + flash[:alert] = "推文已刪除" + else + redirect_to admin_root_path + flash[:alert] = "非禮勿刪" + end end + end diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index 3ba9f0a36..e29ec1db2 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -1,4 +1,8 @@ class Admin::UsersController < Admin::BaseController + before_action :authenticate_admin + def index + @users = User.order(tweets_count: :desc).page(params[:page]).per(10) end + end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 0da627f1a..3524a0388 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,7 +1,17 @@ class ApplicationController < ActionController::Base protect_from_forgery with: :exception + before_action :configure_permitted_parameters, if: :devise_controller? + before_action :authenticate_user! # 請參考 Devise 文件自訂表單後通過 Strong Parameters 的方法 # https://github.com/plataformatec/devise#strong-parameters # 注意有 sign_up 和 account_update 兩種參數要處理 + + protected + + def configure_permitted_parameters + devise_parameter_sanitizer.permit(:sign_up, keys: [:name]) + devise_parameter_sanitizer.permit(:acount_update, keys: [:name]) + end + end diff --git a/app/controllers/followships_controller.rb b/app/controllers/followships_controller.rb index 05f01b552..0e052e389 100644 --- a/app/controllers/followships_controller.rb +++ b/app/controllers/followships_controller.rb @@ -1,7 +1,22 @@ class FollowshipsController < ApplicationController + def create + @followship = current_user.followships.build(following_id: params[:following_id]) + @user = User.find(params[:following_id]) + if @user == current_user + flash[:alert] = @followship.errors.full_messages.to_sentence + redirect_back(fallback_location: root_path) + else + @followship.save + flash[:notice] = "Successfully followed" + redirect_back(fallback_location: root_path) + end end def destroy + @followship = current_user.followships.where(following_id: params[:id]).first + @followship.destroy + flash[:alert] = "Followship destroyed" + redirect_back(fallback_location: root_path) end end diff --git a/app/controllers/replies_controller.rb b/app/controllers/replies_controller.rb index a9b6a315b..5f2fdead6 100644 --- a/app/controllers/replies_controller.rb +++ b/app/controllers/replies_controller.rb @@ -1,9 +1,23 @@ class RepliesController < ApplicationController def index + @tweet = Tweet.find(params[:tweet_id]) + @replies = @tweet.replies.order('created_at desc') + @user = current_user + @reply = Reply.new end def create + @tweet = Tweet.find(params[:tweet_id]) + @reply = @tweet.replies.build(reply_params) + @reply.user = current_user + @reply.save! + redirect_to tweet_replies_path(@tweet) end + private + + def reply_params + params.require(:reply).permit(:comment) + end end diff --git a/app/controllers/tweets_controller.rb b/app/controllers/tweets_controller.rb index ad14115c1..8c41f4a67 100644 --- a/app/controllers/tweets_controller.rb +++ b/app/controllers/tweets_controller.rb @@ -1,16 +1,39 @@ class TweetsController < ApplicationController def index - @users # 基於測試規格,必須講定變數名稱,請用此變數中存放關注人數 Top 10 的使用者資料 + @tweets = Tweet.all.order('created_at desc') + @users = User.all.order(followers_count: :desc).limit(10) + @tweet = Tweet.new end def create + @user = current_user + @tweet = @user.tweets.build(tweet_params) + if @tweet.save + flash[:notice] = "Successfully tweet" + redirect_to tweets_path + elsif @tweet.errors.any? + flash[:alert] = @tweet.errors.full_messages.to_sentence + redirect_to tweets_path + end end def like + @tweet = Tweet.find(params[:id]) + @tweet.likes.create!(user: current_user) + redirect_to tweets_path end def unlike + @tweet = Tweet.find(params[:id]) + like = Like.where(tweet: @tweet, user: current_user) + like.destroy_all + redirect_to tweets_path end + private + + def tweet_params + params.require(:tweet).permit(:description) + end end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 750e3c6b5..1cdb6ca54 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1,24 +1,46 @@ class UsersController < ApplicationController + before_action :set_user, only:[:tweets, :edit, :update, :followings, :followers, :likes] def tweets + @tweets = @user.tweets.all.order(created_at: :desc) end def edit + unless @user == current_user + redirect_to tweets_user_path(@user) + end end def update + if @user.update(user_params) + flash[:notice] = "Profile was successfully update" + redirect_to tweets_user_path(@user) + else + flash[:alert] = "Profile was failed to update" + render :edit + end end def followings - @followings # 基於測試規格,必須講定變數名稱 + @followings = @user.followings.all end def followers - @followers # 基於測試規格,必須講定變數名稱 + @followers = @user.followers.all end def likes - @likes # 基於測試規格,必須講定變數名稱 + @likes = @user.liked_tweets + end + + private + + def user_params + params.require(:user).permit(:name, :introduction, :avatar) + end + + def set_user + @user = User.find(params[:id]) end end diff --git a/app/models/followship.rb b/app/models/followship.rb index 1aed01396..df693227e 100644 --- a/app/models/followship.rb +++ b/app/models/followship.rb @@ -1,4 +1,12 @@ class Followship < ApplicationRecord - validates :following_id, uniqueness: { scope: :user_id } + validates :following_id, uniqueness: {scope: :user_id } + after_save :update_to_user + belongs_to :user + belongs_to :following, class_name: "User" + + def update_to_user + self.following.followers_count! + end + end diff --git a/app/models/like.rb b/app/models/like.rb index d99b93a32..0d1910145 100644 --- a/app/models/like.rb +++ b/app/models/like.rb @@ -1,2 +1,4 @@ class Like < ApplicationRecord + belongs_to :user, counter_cache: true + belongs_to :tweet, counter_cache: true end diff --git a/app/models/reply.rb b/app/models/reply.rb index bae6f9463..83ce4bff9 100644 --- a/app/models/reply.rb +++ b/app/models/reply.rb @@ -1,2 +1,5 @@ class Reply < ApplicationRecord + belongs_to :user + belongs_to :tweet, counter_cache: true + end diff --git a/app/models/tweet.rb b/app/models/tweet.rb index 6715fada2..49b27d9e4 100644 --- a/app/models/tweet.rb +++ b/app/models/tweet.rb @@ -1,4 +1,15 @@ class Tweet < ApplicationRecord validates_length_of :description, maximum: 140 + belongs_to :user, counter_cache: true + + has_many :replies, dependent: :destroy + + has_many :likes, dependent: :destroy + has_many :liked_users, through: :likes, source: :user + + def is_liked?(user) + self.liked_users.include?(user) + end + end diff --git a/app/models/user.rb b/app/models/user.rb index 6b05b8c21..5740bcefb 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,14 +1,38 @@ class User < ApplicationRecord + validates_uniqueness_of :name + validates_presence_of :name + mount_uploader :avatar, AvatarUploader + + has_many :tweets, dependent: :destroy + + has_many :replies, dependent: :restrict_with_error + + has_many :followships, dependent: :destroy + has_many :followings, through: :followships + + has_many :inverse_followships, class_name: "Followship", foreign_key: "following_id" + has_many :followers, through: :inverse_followships, source: :user + + has_many :likes, dependent: :destroy + has_many :liked_tweets, through: :likes, source: :tweet + # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable and :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable - mount_uploader :avatar, AvatarUploader + + def admin? + self.role == "admin" + end - # 需要 app/views/devise 裡找到樣板,加上 name 屬性 - # 並參考 Devise 文件自訂表單後通過 Strong Parameters 的方法 - validates_presence_of :name - # 加上驗證 name 不能重覆 (關鍵字提示: uniqueness) + def following?(user) + self.followings.include?(user) + end + def followers_count! + self.update(followers_count: + self.followers.count) + end + end diff --git a/app/uploaders/avatar_uploader.rb b/app/uploaders/avatar_uploader.rb index a4a41560e..aa0898aac 100644 --- a/app/uploaders/avatar_uploader.rb +++ b/app/uploaders/avatar_uploader.rb @@ -4,7 +4,11 @@ class AvatarUploader < CarrierWave::Uploader::Base # include CarrierWave::MiniMagick # Choose what kind of storage to use for this uploader: - storage :file + if Rails.env.production? + storage :fog + else + storage :file + end # storage :fog # Override the directory where uploaded files will be stored. @@ -15,18 +19,10 @@ def store_dir # 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/" +["avatar.png"].compact.join('_')) - # # - # # "/images/fallback/" + [version_name, "default.png"].compact.join('_') - # end - # - # version :thumb do - # process resize_to_fit: [50, 50] - # end + # # For Rails 3.1+ asset pipeline compatibility: + # # ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_')) # - # version :medium do - # process resize_to_fit: [150, 150] + # "/images/fallback/" + [version_name, "default.png"].compact.join('_') # end # Process files as they are uploaded: diff --git a/app/views/admin/tweets/index.html.erb b/app/views/admin/tweets/index.html.erb new file mode 100644 index 000000000..d43a7bfd3 --- /dev/null +++ b/app/views/admin/tweets/index.html.erb @@ -0,0 +1,52 @@ +
+
+ +
+

Tweet後台

+
+ <%= link_to "All Tweets", admin_tweets_path %> | + <%= link_to "All Users", admin_users_path %> +
+ +
+
+ +
+
+ + + + + + + + + + <% @tweets.each do |t|%> + + + + + <% end %> + + + +
+ <%= paginate @tweets %> +
+ + + + diff --git a/app/views/admin/users/index.html.erb b/app/views/admin/users/index.html.erb new file mode 100644 index 000000000..13f353e52 --- /dev/null +++ b/app/views/admin/users/index.html.erb @@ -0,0 +1,49 @@ +
+
+ +
+

Tweet後台

+
+ <%= link_to "All Tweets", admin_tweets_path %> | + <%= link_to "All Users", admin_users_path %> +
+ +
+
+ +
+
+
#Tweet#
<%= t.id %> +
+ <%= link_to "@#{t.user.name}", tweets_user_path(t.user) %>, + <%= t.created_at.strftime("%Y-%m-%d %H:%M")%> +
+
+ <%= t.description %> +
+ <%= link_to "Reply(#{t.replies.count})", tweet_replies_path(t) %> +
+
+ <%= link_to "Delete", admin_tweet_path(t), method: :delete, data: {confirm:"Are you sure?"} %> +
+ + + + + + + + <% @users.each do |u|%> + + + + + <% end %> + + + +
+ <%= paginate @users %> +
+ + + + \ No newline at end of file diff --git a/app/views/devise/registrations/edit.html.erb b/app/views/devise/registrations/edit.html.erb index 10ed32a9e..d74c74c9b 100644 --- a/app/views/devise/registrations/edit.html.erb +++ b/app/views/devise/registrations/edit.html.erb @@ -1,43 +1,54 @@ -

Edit <%= resource_name.to_s.humanize %>

- -<%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %> - <%= devise_error_messages! %> - -
- <%= f.label :email %>
- <%= f.email_field :email, autofocus: true, autocomplete: "email" %> -
- - <% if devise_mapping.confirmable? && resource.pending_reconfirmation? %> -
Currently waiting confirmation for: <%= resource.unconfirmed_email %>
- <% end %> - -
- <%= f.label :password %> (leave blank if you don't want to change it)
- <%= f.password_field :password, autocomplete: "off" %> - <% if @minimum_password_length %> -
- <%= @minimum_password_length %> characters minimum +
+
+ +

Edit <%= resource_name.to_s.humanize %>

+ + <%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %> + <%= devise_error_messages! %> + +
+ <%= f.label :name, "User name" %>
+ <%= f.text_field :name, autofocus: true %> +
+ +
+ <%= f.label :email %>
+ <%= f.email_field :email, autofocus: true, autocomplete: "email" %> +
+ + <% if devise_mapping.confirmable? && resource.pending_reconfirmation? %> +
Currently waiting confirmation for: <%= resource.unconfirmed_email %>
+ <% end %> + +
+ <%= f.label :password %> (leave blank if you don't want to change it)
+ <%= f.password_field :password, autocomplete: "off" %> + <% if @minimum_password_length %> +
+ <%= @minimum_password_length %> characters minimum + <% end %> +
+ +
+ <%= f.label :password_confirmation %>
+ <%= f.password_field :password_confirmation, autocomplete: "off" %> +
+ +
+ <%= f.label :current_password %> (we need your current password to confirm your changes)
+ <%= f.password_field :current_password, autocomplete: "off" %> +
+ +
+ <%= f.submit "Update" %> +
<% end %> -
-
- <%= f.label :password_confirmation %>
- <%= f.password_field :password_confirmation, autocomplete: "off" %> -
- -
- <%= f.label :current_password %> (we need your current password to confirm your changes)
- <%= f.password_field :current_password, autocomplete: "off" %> -
+

Cancel my account

-
- <%= f.submit "Update" %> -
-<% end %> - -

Cancel my account

+

Unhappy? <%= button_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete %>

-

Unhappy? <%= button_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete %>

+ <%= link_to "Back", :back %> -<%= link_to "Back", :back %> +
+
diff --git a/app/views/devise/registrations/new.html.erb b/app/views/devise/registrations/new.html.erb index 602803cff..a7806b3ef 100644 --- a/app/views/devise/registrations/new.html.erb +++ b/app/views/devise/registrations/new.html.erb @@ -1,29 +1,40 @@ -

Sign up

+
+
-<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %> - <%= devise_error_messages! %> +

Sign up

-
- <%= f.label :email %>
- <%= f.email_field :email, autofocus: true, autocomplete: "email" %> -
+ <%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %> + <%= devise_error_messages! %> -
- <%= f.label :password %> - <% if @minimum_password_length %> - (<%= @minimum_password_length %> characters minimum) - <% end %>
- <%= f.password_field :password, autocomplete: "off" %> -
+
+ <%= f.label :name, "User name" %>
+ <%= f.text_field :name, autofocus: true %> +
+ +
+ <%= f.label :email %>
+ <%= f.email_field :email, autofocus: true, autocomplete: "email" %> +
-
- <%= f.label :password_confirmation %>
- <%= f.password_field :password_confirmation, autocomplete: "off" %> -
+
+ <%= f.label :password %> + <% if @minimum_password_length %> + (<%= @minimum_password_length %> characters minimum) + <% end %>
+ <%= f.password_field :password, autocomplete: "off" %> +
-
- <%= f.submit "Sign up" %> -
-<% end %> +
+ <%= f.label :password_confirmation %>
+ <%= f.password_field :password_confirmation, autocomplete: "off" %> +
-<%= render "devise/shared/links" %> +
+ <%= f.submit "Sign up" %> +
+ <% end %> + + <%= render "devise/shared/links" %> + +
+
diff --git a/app/views/devise/sessions/new.html.erb b/app/views/devise/sessions/new.html.erb index 3ebb001d1..898ccea17 100644 --- a/app/views/devise/sessions/new.html.erb +++ b/app/views/devise/sessions/new.html.erb @@ -1,26 +1,32 @@ -

Log in

+
+
+ +

Log in

-<%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %> -
- <%= f.label :email %>
- <%= f.email_field :email, autofocus: true, autocomplete: "email" %> -
+ <%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %> +
+ <%= f.label :email %>
+ <%= f.email_field :email, autofocus: true, autocomplete: "email" %> +
-
- <%= f.label :password %>
- <%= f.password_field :password, autocomplete: "off" %> -
+
+ <%= f.label :password %>
+ <%= f.password_field :password, autocomplete: "off" %> +
- <% if devise_mapping.rememberable? -%> -
- <%= f.check_box :remember_me %> - <%= f.label :remember_me %> -
- <% end -%> + <% if devise_mapping.rememberable? -%> +
+ <%= f.check_box :remember_me %> + <%= f.label :remember_me %> +
+ <% end -%> -
- <%= f.submit "Log in" %> -
-<% end %> +
+ <%= f.submit "Log in" %> +
+ <% end %> -<%= render "devise/shared/links" %> + <%= render "devise/shared/links" %> + +
+
diff --git a/app/views/kaminari/_first_page.html.erb b/app/views/kaminari/_first_page.html.erb new file mode 100644 index 000000000..2c5985bc9 --- /dev/null +++ b/app/views/kaminari/_first_page.html.erb @@ -0,0 +1,3 @@ +
  • + <%= link_to_unless current_page.first?, raw(t 'views.pagination.first'), url, remote: remote %> +
  • diff --git a/app/views/kaminari/_gap.html.erb b/app/views/kaminari/_gap.html.erb new file mode 100644 index 000000000..6d3a1490c --- /dev/null +++ b/app/views/kaminari/_gap.html.erb @@ -0,0 +1,3 @@ +
  • + <%= content_tag :a, raw(t 'views.pagination.truncate') %> +
  • diff --git a/app/views/kaminari/_last_page.html.erb b/app/views/kaminari/_last_page.html.erb new file mode 100644 index 000000000..aee252478 --- /dev/null +++ b/app/views/kaminari/_last_page.html.erb @@ -0,0 +1,3 @@ +
  • + <%= link_to_unless current_page.last?, raw(t 'views.pagination.last'), url, { remote: remote } %> +
  • diff --git a/app/views/kaminari/_next_page.html.erb b/app/views/kaminari/_next_page.html.erb new file mode 100644 index 000000000..8e9a10e6a --- /dev/null +++ b/app/views/kaminari/_next_page.html.erb @@ -0,0 +1,3 @@ +
  • + <%= link_to_unless current_page.last?, raw(t 'views.pagination.next'), url, rel: 'next', remote: remote %> +
  • diff --git a/app/views/kaminari/_page.html.erb b/app/views/kaminari/_page.html.erb new file mode 100644 index 000000000..19c420634 --- /dev/null +++ b/app/views/kaminari/_page.html.erb @@ -0,0 +1,9 @@ +<% if page.current? %> +
  • + <%= content_tag :a, page, data: { remote: remote }, rel: (page.next? ? 'next' : (page.prev? ? 'prev' : nil)) %> +
  • +<% else %> +
  • + <%= link_to page, url, remote: remote, rel: (page.next? ? 'next' : (page.prev? ? 'prev' : nil)) %> +
  • +<% end %> diff --git a/app/views/kaminari/_paginator.html.erb b/app/views/kaminari/_paginator.html.erb new file mode 100644 index 000000000..2c8757b4f --- /dev/null +++ b/app/views/kaminari/_paginator.html.erb @@ -0,0 +1,15 @@ +<%= paginator.render do -%> +
      + <%= first_page_tag unless current_page.first? %> + <%= prev_page_tag unless current_page.first? %> + <% each_page do |page| -%> + <% if page.left_outer? || page.right_outer? || page.inside_window? -%> + <%= page_tag page %> + <% elsif !page.was_truncated? -%> + <%= gap_tag %> + <% end -%> + <% end -%> + <%= next_page_tag unless current_page.last? %> + <%= last_page_tag unless current_page.last? %> +
    +<% end -%> diff --git a/app/views/kaminari/_prev_page.html.erb b/app/views/kaminari/_prev_page.html.erb new file mode 100644 index 000000000..f16f6b4bd --- /dev/null +++ b/app/views/kaminari/_prev_page.html.erb @@ -0,0 +1,3 @@ +
  • + <%= link_to_unless current_page.first?, raw(t 'views.pagination.previous'), url, rel: 'prev', remote: remote %> +
  • diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 952cb7a1b..8d3e35d85 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -9,20 +9,65 @@ - <% if current_user %> - <% if current_user&.admin? %> -
  • <%= link_to 'Admin Panel', admin_restaurants_path %>
  • - <% end %> -
  • -
  • <%= link_to('登出', destroy_user_session_path, method: :delete) %>
  • -
  • <%= link_to('修改個人資料', edit_user_path(current_user)) %>
  • -
  • <%= link_to('修改密碼', edit_user_registration_path) %>
  • - <% else %> -
  • <%= link_to('註冊', new_user_registration_path) %>
  • -
  • <%= link_to('登入', new_user_session_path) %>
  • + + + + + <% if flash[:notice] %> +
    +
    + +
    +
    <% end %> -

    <%= notice %>

    -

    <%= alert %>

    + + <% if flash[:alert] %> +
    +
    + +
    +
    + <% end %> + <%= yield %> diff --git a/app/views/replies/index.html.erb b/app/views/replies/index.html.erb new file mode 100644 index 000000000..b69df7775 --- /dev/null +++ b/app/views/replies/index.html.erb @@ -0,0 +1,71 @@ +
    +
    + +
    + + <%= render partial: "shared/user_info"%> + +
    + +
    +

    Tweets

    +
    +
    +
    +
    + <%= image_tag @tweet.user.avatar, size: 80%> +
    + +
    + <%= link_to tweets_user_path(@tweet.user) do%> + <%= "@"+@tweet.user.name+"," %> + <%= @tweet.created_at.strftime("%Y-%m-%d %H:%M") %> + <% end%> +
    + <%= @tweet.description %> +
    + <%= link_to "Reply(#{@tweet.replies.count.to_s})", tweet_replies_path(@tweet) %> + + <% if @tweet.user != current_user %> + <%= render partial: "shared/like", locals: {tweet: @tweet} %> + <% end %> +
    + +
    +
    + +

    Replies

    +
    + <% @replies.each do |r| %> +
    +
    +
    + <%= image_tag r.user.avatar, size: 80%> +
    + +
    + <%= link_to tweets_user_path(r.user) do%> + <%= "@"+r.user.name+"," %> + <%= r.created_at.strftime("%Y-%m-%d %H:%M") %> + <% end%> +
    + <%= r.comment %> +
    +
    +
    + <% end %> + + <%= form_for [@tweet, @reply] do |f| %> +
    + <%= f.text_area :comment, class:"form-control", rows: "5"%> +
    +
    + +
    + <%= f.submit "Reply", class:"btn btn-primary pull-right" %> +
    + <% end %> +
    + +
    +
    \ No newline at end of file diff --git a/app/views/shared/_follow.html.erb b/app/views/shared/_follow.html.erb new file mode 100644 index 000000000..011f68830 --- /dev/null +++ b/app/views/shared/_follow.html.erb @@ -0,0 +1,7 @@ +<% if user != current_user%> + <% if current_user.following?(user) %> + <%= link_to "Unfollow", followship_path(user), method: :delete, class:"btn btn-primary" %> + <% else %> + <%= link_to "Follow", followships_path(following_id: user), method: :post, class:"btn btn-primary" %> + <% end %> +<% end %> \ No newline at end of file diff --git a/app/views/shared/_like.html.erb b/app/views/shared/_like.html.erb new file mode 100644 index 000000000..8c3ba96e6 --- /dev/null +++ b/app/views/shared/_like.html.erb @@ -0,0 +1,5 @@ +<% if tweet.is_liked?(current_user) %> + <%= link_to "Unlike", unlike_tweet_path(tweet), method: :post %> +<% else%> + <%= link_to "Like(#{tweet.likes.count})", like_tweet_path(tweet), method: :post %> +<% end %> \ No newline at end of file diff --git a/app/views/shared/_user_info.html.erb b/app/views/shared/_user_info.html.erb new file mode 100644 index 000000000..39cd92425 --- /dev/null +++ b/app/views/shared/_user_info.html.erb @@ -0,0 +1,15 @@ +<%= image_tag @user.avatar, size:"150"%> +
    +

    <%= @user.name%>

    +<%= @user.introduction%> +
    +

    <%= link_to "Tweet " + @user.tweets.count.to_s, tweets_user_path(@user) %>

    +

    <%= link_to "Following " + @user.followings.count.to_s, followings_user_path(@user) %>

    +

    <%= link_to "Followers " + @user.followers.count.to_s, followers_user_path(@user) %>

    +

    <%= link_to "Likes " + @user.likes.count.to_s, likes_user_path(@user) %>

    +
    +<% if @user == current_user %> + <%= link_to "Edit Profile", edit_user_path(@user), class:"btn btn-primary"%> +<% else %> + <%= render partial: "/shared/follow", locals: {user: @user} %> +<% end %> \ No newline at end of file diff --git a/app/views/tweets/index.html.erb b/app/views/tweets/index.html.erb new file mode 100644 index 000000000..e73457afb --- /dev/null +++ b/app/views/tweets/index.html.erb @@ -0,0 +1,87 @@ +
    +
    + +
    +
    + <%= form_for [@user, @tweet] do |f| %> +
    + <%= f.text_area :description, + placeholder: "What's on your mind?", + class: "form-control", + rows: "5", + maxlength:"140" %> +
    +
    + <%= f.submit "Tweet", class: "btn btn-primary" %> +
    + <% end %> +
    + + +
    + + <% @tweets.each do |t| %> + +
    +
    +
    +
    + <%= image_tag t.user.avatar, size: 80%> +
    + +
    + <%= link_to tweets_user_path(t.user) do%> + <%= "@"+t.user.name+"," %> + <%= t.created_at.strftime("%Y-%m-%d %H:%M") %> + <% end%> +
    + <%= t.description %> +
    + <%= link_to "Reply(#{t.replies.count})", tweet_replies_path(t) %> + <% if t.user != current_user %> + <%= render partial: "shared/like", locals: {tweet: t} %> + <% end%> +
    + +
    +
    +
    + + <% end%> +
    + +
    +

    Popular

    +
    + <% @users.each do |u| %> + +
    +
    +
    +
    + <%= image_tag u.avatar, size: 80%> +
    + +
    + <%= link_to tweets_user_path(u) do%> + <%= "@"+u.name %> + <% end%> +
    + <%= u.introduction %> +
    + +
    + +
    +
    +
    + + <% end%> +
    + +
    + +
    +
    \ No newline at end of file diff --git a/app/views/users/edit.html.erb b/app/views/users/edit.html.erb new file mode 100644 index 000000000..22e754bd8 --- /dev/null +++ b/app/views/users/edit.html.erb @@ -0,0 +1,48 @@ +
    +
    + +
    + + + <%= form_for @user, :url => user_path(@user), :method => :patch do |f| %> +
    +
    +
    + +
    + <%= image_tag @user.avatar , size:"150" %> +
    +
    +
    + +
    +
    + <%= link_to "Chang password", edit_user_registration_path, class: "btn btn-primary" %> + +
    +
    +
    + + +
    +
    + <%= f.text_field :name, placeholder: "Name", class: "form-control" %> +
    +
    + <%= f.text_area :introduction, placeholder: "Type anything about you here.....", class: "form-control", rows: "5" %> +
    +
    + <%= f.submit "Update", class: "btn btn-primary pull-right"%> +
    +
    + <% end %> + +
    + +
    +
    \ No newline at end of file diff --git a/app/views/users/followers.html.erb b/app/views/users/followers.html.erb new file mode 100644 index 000000000..e398acc79 --- /dev/null +++ b/app/views/users/followers.html.erb @@ -0,0 +1,39 @@ +
    +
    + +
    + + <%= render partial: "shared/user_info"%> + +
    + +
    +

    Followers

    +
    +
    + <% @followers.each do |f| %> +
    +
    +
    + <%= image_tag f.avatar, size: "80"%> +
    +
    + <%= link_to tweets_user_path(f) do%> + <%= "@#{f.name}" %> + <% end %> +
    + <%= f.introduction %> +
    + +
    +
    +
    + <% end %> +
    +
    +
    + +
    +
    \ No newline at end of file diff --git a/app/views/users/followings.html.erb b/app/views/users/followings.html.erb new file mode 100644 index 000000000..1f6a967ed --- /dev/null +++ b/app/views/users/followings.html.erb @@ -0,0 +1,39 @@ +
    +
    + +
    + + <%= render partial: "shared/user_info"%> + +
    + +
    +

    Following

    +
    +
    + <% @followings.each do |f| %> +
    +
    +
    + <%= image_tag f.avatar, size: "80"%> +
    +
    + <%= link_to tweets_user_path(f) do%> + <%= "@#{f.name}" %> + <% end %> +
    + <%= f.introduction %> +
    + +
    +
    +
    + <% end %> +
    +
    +
    + +
    +
    \ No newline at end of file diff --git a/app/views/users/likes.html.erb b/app/views/users/likes.html.erb new file mode 100644 index 000000000..0336cc135 --- /dev/null +++ b/app/views/users/likes.html.erb @@ -0,0 +1,34 @@ +
    +
    + +
    + + <%= render partial: "shared/user_info"%> + +
    + +
    +

    Likes

    + <% @likes.each do |l| %> +
    +
    +
    + <%= image_tag l.user.avatar, size: "80"%> +
    +
    + <%= link_to tweets_user_path(l.user) do%> + <%= "@#{l.user.name}" %> + <% end %> +
    + <%= l.description %> +
    + <%= link_to "Reply(#{l.replies.count})", tweet_replies_path(l)%> + <%= render partial: "shared/like", locals: {tweet: l} %> +
    +
    +
    + <% end %> +
    + +
    +
    \ No newline at end of file diff --git a/app/views/users/tweets.html.erb b/app/views/users/tweets.html.erb new file mode 100644 index 000000000..05da27f2e --- /dev/null +++ b/app/views/users/tweets.html.erb @@ -0,0 +1,42 @@ +
    +
    + +
    + + <%= render partial: "shared/user_info"%> + +
    + +
    + <% @tweets.each do |t| %> +
    +
    +
    +
    + <%= image_tag t.user.avatar, size: 80%> +
    + +
    + <%= link_to tweets_user_path(t.user) do%> + <%= "@"+t.user.name+"," %> + <%= t.created_at.strftime("%Y-%m-%d %H:%M") %> + <% end%> +
    + <%= t.description %> +
    + <%= link_to "Reply(#{t.replies.count})", tweet_replies_path(t) %> + <% if t.user != current_user %> + <%= render partial: "shared/like", locals: {tweet: t} %> + <% end %> +
    + +
    +
    +
    + + <% end%> + <%= %> +
    + +
    +
    \ No newline at end of file diff --git a/bin/rails b/bin/rails index 073966023..5badb2fde 100755 --- a/bin/rails +++ b/bin/rails @@ -1,4 +1,9 @@ #!/usr/bin/env ruby +begin + load File.expand_path('../spring', __FILE__) +rescue LoadError => e + raise unless e.message.include?('spring') +end APP_PATH = File.expand_path('../config/application', __dir__) require_relative '../config/boot' require 'rails/commands' diff --git a/bin/rake b/bin/rake index 17240489f..d87d5f578 100755 --- a/bin/rake +++ b/bin/rake @@ -1,4 +1,9 @@ #!/usr/bin/env ruby +begin + load File.expand_path('../spring', __FILE__) +rescue LoadError => e + raise unless e.message.include?('spring') +end require_relative '../config/boot' require 'rake' Rake.application.run diff --git a/bin/spring b/bin/spring new file mode 100755 index 000000000..fb2ec2ebb --- /dev/null +++ b/bin/spring @@ -0,0 +1,17 @@ +#!/usr/bin/env ruby + +# This file loads spring without using Bundler, in order to be fast. +# It gets overwritten when you run the `spring binstub` command. + +unless defined?(Spring) + require 'rubygems' + require 'bundler' + + lockfile = Bundler::LockfileParser.new(Bundler.default_lockfile.read) + spring = lockfile.specs.detect { |spec| spec.name == "spring" } + if spring + Gem.use_paths Gem.dir, Bundler.bundle_path.to_s, *Gem.path + gem 'spring', spring.version + require 'spring/binstub' + end +end diff --git a/config/database.yml b/config/database.yml index 0d02f2498..1c8d40f2a 100644 --- a/config/database.yml +++ b/config/database.yml @@ -21,5 +21,5 @@ test: database: db/test.sqlite3 production: - <<: *default - database: db/production.sqlite3 + adapter: postgresql + encoding: Unicode diff --git a/config/initializers/carrierwave.rb b/config/initializers/carrierwave.rb new file mode 100644 index 000000000..37b89fc66 --- /dev/null +++ b/config/initializers/carrierwave.rb @@ -0,0 +1,14 @@ +CarrierWave.configure do |config| + config.fog_provider = 'fog/aws' + if Rails.env.production? + config.fog_credentials = { + provider: 'AWS', + aws_access_key_id: ENV['S3_KEY'], + aws_secret_access_key: ENV['S3_SECRET'], + region: 'ap-northeast-1' + } + config.fog_directory = ENV['S3_BUCKET'] + else + config.storage :file + end +end \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index 90856d4fe..c490bfac5 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,7 +1,36 @@ Rails.application.routes.draw do - # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html devise_for :users + # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html + resources :tweets, only: [:index, :create ] do + resources :replies, only: [:index, :create] + + member do + post :like + post :unlike + end + + end + + + + root "tweets#index" + + resources :users, only: [:edit, :update] do + + member do + get :tweets + get :followings + get :followers + get :likes + end + + end - # 請依照專案指定規格來設定路由 + resources :followships, only: [:create, :destroy] + namespace :admin do + resources :tweets, only: [:index, :destroy] + resources :users, only: [:index] + root "tweets#index" + end end diff --git a/db/migrate/20180812023610_add_column_to_user_table.rb b/db/migrate/20180812023610_add_column_to_user_table.rb new file mode 100644 index 000000000..8cce47416 --- /dev/null +++ b/db/migrate/20180812023610_add_column_to_user_table.rb @@ -0,0 +1,5 @@ +class AddColumnToUserTable < ActiveRecord::Migration[5.1] + def change + add_column :users, :tweets_count, :integer, default: 0 + end +end diff --git a/db/schema.rb b/db/schema.rb index 6a6842c86..2ffb1a14b 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20180201102838) do +ActiveRecord::Schema.define(version: 20180812023610) do create_table "followships", force: :cascade do |t| t.integer "user_id" @@ -66,6 +66,7 @@ t.integer "likes_count", default: 0 t.string "role", default: "normal" t.integer "followers_count", default: 0 + t.integer "tweets_count", default: 0 t.index ["email"], name: "index_users_on_email", unique: true t.index ["name"], name: "index_users_on_name", unique: true t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true diff --git a/lib/tasks/dev.rake b/lib/tasks/dev.rake index 9b1e87ae4..05c101a24 100644 --- a/lib/tasks/dev.rake +++ b/lib/tasks/dev.rake @@ -1,23 +1,86 @@ namespace :dev do - # 請先執行 rails dev:fake_user,可以產生 20 個資料完整的 User 紀錄 - # 其他測試用的假資料請依需要自行撰寫 task fake_user: :environment do User.destroy_all - 20.times do |i| - name = FFaker::Name::first_name - file = File.open("#{Rails.root}/public/avatar/user#{i+1}.jpg") - - user = User.new( - name: name, - email: "#{name}@example.co", - password: "12345678", - introduction: FFaker::Lorem::sentence(30), - avatar: file - ) - - user.save! - puts user.name + User.create(email: "test@test.com", password: "000000", name: "RT", role: "admin") + puts "Default admin created!" + + url = "https://uinames.com/api/?ext®ion=england" + + 50.times do + response = RestClient.get(url) + data = JSON.parse(response.body) + + user = User.create!( + email: data["email"], + password:"000000", + name: FFaker::Name::first_name, + introduction: FFaker::Lorem.paragraph, + remote_avatar_url: data["photo"] + ) + end + + puts "have created fake users" + puts "now you have #{User.count} users data" + end + + task fake_tweet: :environment do + Tweet.destroy_all + + User.all.each do |u| + 25.times do + u.tweets.create!( + description: FFaker::Tweet.tweet, + ) + end + end + + puts "have created fake tweets" + puts "now you have #{Tweet.count} tweets data" + end + + task fake_reply: :environment do + Reply.destroy_all + + Tweet.all.each do |t| + 5.times do + t.replies.create!(comment: FFaker::Lorem.phrase, + user: User.all.sample) + end end + + puts "have created fake replies" + puts "now you have #{Reply.count} replies data" + end + + task fake_followship: :environment do + Followship.destroy_all + + User.all.each do |u| + @users = User.where.not(id: u.id).shuffle + 20.times do + u.followships.create!( + following: @users.pop, + ) + end + end + + puts "have created fake followship" + puts "now you have #{Followship.count} folloings data" + end + + task fake_like: :environment do + Like.destroy_all + + User.all.each do |u| + 20.times do + u.likes.create!( + tweet: Tweet.all.sample, + ) + end + end + + puts "have created fake like" + puts "now you have #{Like.count} fake like data" end end diff --git a/test/application_system_test_case.rb b/test/application_system_test_case.rb new file mode 100644 index 000000000..d19212abd --- /dev/null +++ b/test/application_system_test_case.rb @@ -0,0 +1,5 @@ +require "test_helper" + +class ApplicationSystemTestCase < ActionDispatch::SystemTestCase + driven_by :selenium, using: :chrome, screen_size: [1400, 1400] +end diff --git a/test/controllers/.keep b/test/controllers/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/test/controllers/admin/tweets_controller_test.rb b/test/controllers/admin/tweets_controller_test.rb new file mode 100644 index 000000000..c81dee823 --- /dev/null +++ b/test/controllers/admin/tweets_controller_test.rb @@ -0,0 +1,7 @@ +require 'test_helper' + +class Admin::TweetsControllerTest < ActionDispatch::IntegrationTest + # test "the truth" do + # assert true + # end +end diff --git a/test/controllers/admin/users_controller_test.rb b/test/controllers/admin/users_controller_test.rb new file mode 100644 index 000000000..f5657a4a5 --- /dev/null +++ b/test/controllers/admin/users_controller_test.rb @@ -0,0 +1,7 @@ +require 'test_helper' + +class Admin::UsersControllerTest < ActionDispatch::IntegrationTest + # test "the truth" do + # assert true + # end +end diff --git a/test/controllers/followships_controller_test.rb b/test/controllers/followships_controller_test.rb new file mode 100644 index 000000000..da1b26ee1 --- /dev/null +++ b/test/controllers/followships_controller_test.rb @@ -0,0 +1,7 @@ +require 'test_helper' + +class FollowshipsControllerTest < ActionDispatch::IntegrationTest + # test "the truth" do + # assert true + # end +end diff --git a/test/controllers/replies_controller_test.rb b/test/controllers/replies_controller_test.rb new file mode 100644 index 000000000..3f8986cf6 --- /dev/null +++ b/test/controllers/replies_controller_test.rb @@ -0,0 +1,7 @@ +require 'test_helper' + +class RepliesControllerTest < ActionDispatch::IntegrationTest + # test "the truth" do + # assert true + # end +end diff --git a/test/controllers/tweets_controller_test.rb b/test/controllers/tweets_controller_test.rb new file mode 100644 index 000000000..9dfaf2de5 --- /dev/null +++ b/test/controllers/tweets_controller_test.rb @@ -0,0 +1,7 @@ +require 'test_helper' + +class TweetsControllerTest < ActionDispatch::IntegrationTest + # test "the truth" do + # assert true + # end +end diff --git a/test/controllers/users_controller_test.rb b/test/controllers/users_controller_test.rb new file mode 100644 index 000000000..6c3da770c --- /dev/null +++ b/test/controllers/users_controller_test.rb @@ -0,0 +1,7 @@ +require 'test_helper' + +class UsersControllerTest < ActionDispatch::IntegrationTest + # test "the truth" do + # assert true + # end +end diff --git a/test/fixtures/.keep b/test/fixtures/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/test/fixtures/files/.keep b/test/fixtures/files/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/test/fixtures/followships.yml b/test/fixtures/followships.yml new file mode 100644 index 000000000..80aed36e3 --- /dev/null +++ b/test/fixtures/followships.yml @@ -0,0 +1,11 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +# This model initially had no columns defined. If you add columns to the +# model remove the '{}' from the fixture names and add the columns immediately +# below each fixture, per the syntax in the comments below +# +one: {} +# column: value +# +two: {} +# column: value diff --git a/test/fixtures/likes.yml b/test/fixtures/likes.yml new file mode 100644 index 000000000..80aed36e3 --- /dev/null +++ b/test/fixtures/likes.yml @@ -0,0 +1,11 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +# This model initially had no columns defined. If you add columns to the +# model remove the '{}' from the fixture names and add the columns immediately +# below each fixture, per the syntax in the comments below +# +one: {} +# column: value +# +two: {} +# column: value diff --git a/test/fixtures/replies.yml b/test/fixtures/replies.yml new file mode 100644 index 000000000..80aed36e3 --- /dev/null +++ b/test/fixtures/replies.yml @@ -0,0 +1,11 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +# This model initially had no columns defined. If you add columns to the +# model remove the '{}' from the fixture names and add the columns immediately +# below each fixture, per the syntax in the comments below +# +one: {} +# column: value +# +two: {} +# column: value diff --git a/test/fixtures/tweets.yml b/test/fixtures/tweets.yml new file mode 100644 index 000000000..80aed36e3 --- /dev/null +++ b/test/fixtures/tweets.yml @@ -0,0 +1,11 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +# This model initially had no columns defined. If you add columns to the +# model remove the '{}' from the fixture names and add the columns immediately +# below each fixture, per the syntax in the comments below +# +one: {} +# column: value +# +two: {} +# column: value diff --git a/test/fixtures/users.yml b/test/fixtures/users.yml new file mode 100644 index 000000000..80aed36e3 --- /dev/null +++ b/test/fixtures/users.yml @@ -0,0 +1,11 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +# This model initially had no columns defined. If you add columns to the +# model remove the '{}' from the fixture names and add the columns immediately +# below each fixture, per the syntax in the comments below +# +one: {} +# column: value +# +two: {} +# column: value diff --git a/test/helpers/.keep b/test/helpers/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/test/integration/.keep b/test/integration/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/test/mailers/.keep b/test/mailers/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/test/models/.keep b/test/models/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/test/models/followship_test.rb b/test/models/followship_test.rb new file mode 100644 index 000000000..9f503c796 --- /dev/null +++ b/test/models/followship_test.rb @@ -0,0 +1,7 @@ +require 'test_helper' + +class FollowshipTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end diff --git a/test/models/like_test.rb b/test/models/like_test.rb new file mode 100644 index 000000000..1eea9915b --- /dev/null +++ b/test/models/like_test.rb @@ -0,0 +1,7 @@ +require 'test_helper' + +class LikeTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end diff --git a/test/models/reply_test.rb b/test/models/reply_test.rb new file mode 100644 index 000000000..84c263563 --- /dev/null +++ b/test/models/reply_test.rb @@ -0,0 +1,7 @@ +require 'test_helper' + +class ReplyTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end diff --git a/test/models/tweet_test.rb b/test/models/tweet_test.rb new file mode 100644 index 000000000..89667af40 --- /dev/null +++ b/test/models/tweet_test.rb @@ -0,0 +1,7 @@ +require 'test_helper' + +class TweetTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end diff --git a/test/models/user_test.rb b/test/models/user_test.rb new file mode 100644 index 000000000..82f61e010 --- /dev/null +++ b/test/models/user_test.rb @@ -0,0 +1,7 @@ +require 'test_helper' + +class UserTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end diff --git a/test/system/.keep b/test/system/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/test/test_helper.rb b/test/test_helper.rb new file mode 100644 index 000000000..92e39b2d7 --- /dev/null +++ b/test/test_helper.rb @@ -0,0 +1,10 @@ +ENV['RAILS_ENV'] ||= 'test' +require File.expand_path('../../config/environment', __FILE__) +require 'rails/test_help' + +class ActiveSupport::TestCase + # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order. + fixtures :all + + # Add more helper methods to be used by all tests here... +end
    #User Name
    <%= u.id %> +
    + <%= link_to "@"+u.name, tweets_user_path(u) %>, + <%= u.created_at.strftime("%Y-%m-%d %H:%M")%> +
    + <%= link_to " #{u.tweets_count}Tweets ", tweets_user_path(u) %> | + <%= link_to " #{u.followings.count}followings ", followings_user_path(u) %>| + <%= link_to " #{u.followers.count} followers ", followers_user_path(u) %> | + <%= link_to " #{u.likes_count} liked ", likes_user_path(u) %> +
    +