diff --git a/Gemfile b/Gemfile index 3f1e6961..f8ebd5be 100644 --- a/Gemfile +++ b/Gemfile @@ -15,6 +15,7 @@ gem 'sass-rails', '~> 5.0' gem 'uglifier', '>= 1.3.0' # See https://github.com/rails/execjs#readme for more supported runtimes # gem 'mini_racer', platforms: :ruby +gem 'will_paginate', '~> 3.1.0' # Use CoffeeScript for .coffee assets and views gem 'coffee-rails', '~> 4.2' @@ -25,7 +26,7 @@ gem 'jbuilder', '~> 2.5' # Use Redis adapter to run Action Cable in production # gem 'redis', '~> 4.0' # Use ActiveModel has_secure_password -# gem 'bcrypt', '~> 3.1.7' +gem 'bcrypt', '~> 3.1.7' # Use ActiveStorage variant # gem 'mini_magick', '~> 4.8' diff --git a/Gemfile.lock b/Gemfile.lock index 16c3b7bc..563f3aa0 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -220,6 +220,7 @@ GEM websocket-driver (0.7.0) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.3) + will_paginate (3.1.6) xpath (3.0.0) nokogiri (~> 1.8) @@ -227,6 +228,7 @@ PLATFORMS ruby DEPENDENCIES + bcrypt (~> 3.1.7) bootsnap (>= 1.1.0) byebug capybara @@ -249,9 +251,10 @@ DEPENDENCIES tzinfo-data uglifier (>= 1.3.0) web-console (>= 3.3.0) + will_paginate (~> 3.1.0) RUBY VERSION ruby 2.4.4p296 BUNDLED WITH - 1.16.2 + 2.0.1 diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index edb771d6..abafd4ba 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -19,3 +19,90 @@ header { display: flex; justify-content: space-between; } + +body { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; +} + +h1 { + text-shadow: 1px 1px 1px gray; + font-family: sans-serif; +} +.actions a { + margin: 0 20px 0 0; + border: solid 1px black; + border-radius: 2px; + padding: 10px; +} + +a { +text-decoration: none; +padding-bottom: 10px; +} + +.ad { + margin: 30px 0 0 0; +} + +.like-button { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; + background-color: pink; + border-radius: 20px; + height: 25px; + font-size: 12px; + font-weight: 100; + margin-bottom: 10px; +} + +.unlike-button { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; + background-color: lightgray; + height: 25px; + font-size: 12px; + font-weight: 500; + border-radius: 3px; + color: black; +} + +.like-button:hover, .unlike-button:hover { + cursor: pointer; + box-shadow: 1px 1px 1px gray +} + +.dog-name { + font-family: Gaegu; + font-weight: 500; + font-size: 36px; + margin: 30px 0 0 0; + text-shadow: 1px 1px 1px gray; +} + +img { + height: 100px; + border: solid black 3px; + border-radius: 5px; +} + +img:hover { + box-shadow: 3px 3px 6px gray +} +.index-count { + font-size: 12px; + color: gray; + font-style: italic; + font-weight: 400; + margin-top: 0 + +} +.like-count { + font-size: 12px; + color: gray; + font-style: italic; + font-weight: 400; +} + +.description { + font-family: Gaegu; + font-weight: 200; + font-size: 18px; +} diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 09705d12..157d5ac8 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,2 +1,7 @@ class ApplicationController < ActionController::Base + protect_from_forgery with: :exception + + helper_method :current_user, :user_signed_in? + + end diff --git a/app/controllers/dogs_controller.rb b/app/controllers/dogs_controller.rb index cb9eebc5..1ce5e76c 100644 --- a/app/controllers/dogs_controller.rb +++ b/app/controllers/dogs_controller.rb @@ -1,10 +1,38 @@ +require 'will_paginate/array' + class DogsController < ApplicationController before_action :set_dog, only: [:show, :edit, :update, :destroy] # GET /dogs # GET /dogs.json def index - @dogs = Dog.all + unliked_dogs = [] + liked_dogs = [] + liked_ids = Like.where('created_at > ?', 1.hours.ago).pluck(:dog_id) + dogs = liked_ids.map { |id| Dog.find(id) } + Dog.all.each do |dog| + if liked_ids.include?(dog.id) + liked_dogs << dog + else + unliked_dogs << dog + end + end + liked_dogs = dogs.sort_by { |dog| dog.likes.count }.reverse + all_dogs = liked_dogs.concat(unliked_dogs) + @dogs = all_dogs.paginate(:page => params[:page], :per_page => 5) + + # @dogs = Dog.select('dogs.*, count(likes.id) as likes_count') + # .joins('LEFT OUTER JOIN likes on likes.post_id = dogs.id') + # .group_by('dogs.id') + # .order('likes_count desc') + # .where('created_at > ?', 1.hours.ago) + # .paginate(:page => params[:page], :per_page => 5) + + # @dogs = Dog.left_joins(:likes) + # .group(:id) + # .order('COUNT(likes.id) DESC') + # .where('created_at > ?', 1.hours.ago) + # .paginate(:page => params[:page], :per_page => 5) end # GET /dogs/1 @@ -25,6 +53,7 @@ def edit # POST /dogs.json def create @dog = Dog.new(dog_params) + @dog.owner = current_user respond_to do |format| if @dog.save @@ -43,6 +72,15 @@ def create # PATCH/PUT /dogs/1.json def update respond_to do |format| + + if @dog.owner + if @dog.owner.id != current_user.id + flash[:notice] = "*You can't EDIT someone else's dog!*" + redirect_to @dog + end + return + end + if @dog.update(dog_params) @dog.images.attach(params[:dog][:image]) if params[:dog][:image].present? @@ -58,6 +96,14 @@ def update # DELETE /dogs/1 # DELETE /dogs/1.json def destroy + if @dog.owner + if @dog.owner.id != current_user.id + flash[:notice] = "*You can't just DELETE someone else's dog!*" + redirect_to @dog + return + end + end + @dog.destroy respond_to do |format| format.html { redirect_to dogs_url, notice: 'Dog was successfully destroyed.' } @@ -73,6 +119,6 @@ def set_dog # Never trust parameters from the scary internet, only allow the white list through. def dog_params - params.require(:dog).permit(:name, :description, :images) + params.require(:dog).permit(:name, :description, images: [] ) end end diff --git a/app/controllers/likes_controller.rb b/app/controllers/likes_controller.rb new file mode 100644 index 00000000..c42c479a --- /dev/null +++ b/app/controllers/likes_controller.rb @@ -0,0 +1,33 @@ +class LikesController < ApplicationController + before_action :authenticate_user! + +def create + @like = Like.find_by(user_id: current_user.id, dog_id: params[:dog_id]) + @dog = Dog.find(params[:dog_id]) + if @dog.owner.id == current_user.id + flash[:notice] = "*You can't like your own dog!*" + redirect_to @dog + elsif @like + flash[:notice] = "*You can't like the same dog twice!*" + redirect_to @dog + else + @like = Like.new(user_id: current_user.id, dog_id: params[:dog_id]) + @like.save + redirect_to @dog + end +end + +def destroy + @dog = Dog.find(params[:dog_id]) + @like = Like.find_by(user_id: current_user.id, dog_id: params[:dog_id]) + if !@like + flash[:notice] = "*Why would you want to UNlike a dog you haven't even liked?!... No.*" + redirect_to @dog + else + @like.delete + redirect_to @dog + end +end + + +end diff --git a/app/models/dog.rb b/app/models/dog.rb index eb40bf6e..529fc8e2 100644 --- a/app/models/dog.rb +++ b/app/models/dog.rb @@ -1,3 +1,12 @@ class Dog < ApplicationRecord has_many_attached :images + + belongs_to :owner, + class_name: :User, + foreign_key: :user_id, + optional: true + + has_many :likes + + end diff --git a/app/models/like.rb b/app/models/like.rb new file mode 100644 index 00000000..202b8943 --- /dev/null +++ b/app/models/like.rb @@ -0,0 +1,6 @@ +class Like < ApplicationRecord + + belongs_to :user + belongs_to :dog + +end \ No newline at end of file diff --git a/app/models/user.rb b/app/models/user.rb index b2091f9a..ff1a57c5 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -3,4 +3,12 @@ class User < ApplicationRecord # :confirmable, :lockable, :timeoutable and :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable + + + has_many :dogs, + class_name: :Dog, + foreign_key: :user_id + + has_many :likes + end diff --git a/app/views/dogs/_form.html.erb b/app/views/dogs/_form.html.erb index 6dfc7dc9..3fd29f7e 100644 --- a/app/views/dogs/_form.html.erb +++ b/app/views/dogs/_form.html.erb @@ -1,7 +1,7 @@ <%= simple_form_for @dog do |f| %> <%= f.input :name %> <%= f.input :description, as: :text %> - <%= f.input :image, as: :file %> + <%= f.input :images, :input_html => { :multiple => true }%> <% if @dog.images.any? %> <%= image_tag @dog.images.first %> diff --git a/app/views/dogs/_thumbnail.html.erb b/app/views/dogs/_thumbnail.html.erb index 4d6bb441..b3a92087 100644 --- a/app/views/dogs/_thumbnail.html.erb +++ b/app/views/dogs/_thumbnail.html.erb @@ -1,6 +1,7 @@

<%= dog.name %>

+

Likes: <%= dog.likes.count %>

<%= image_tag url_for(dog.images.first), class: "dog-photo", alt: "Photo of #{dog.name}" %>
diff --git a/app/views/dogs/index.html.erb b/app/views/dogs/index.html.erb index 91ea5603..0c69ecdf 100644 --- a/app/views/dogs/index.html.erb +++ b/app/views/dogs/index.html.erb @@ -1 +1,17 @@ -<%= render partial: 'thumbnail', collection: @dogs, as: :dog %> + +<%= will_paginate @dogs %> + +<% count = 0 %> +<% @dogs.each do |dog| %> + <%= render partial: 'thumbnail', object: dog, as: 'dog' %> + <% count += 1 %> + <% if count == 2 %> +
+

You may be interested in:

+ +
+ <% count = 0 %> + <% end %> +<% end %> + +<%= will_paginate @dogs %> \ No newline at end of file diff --git a/app/views/dogs/show.html.erb b/app/views/dogs/show.html.erb index 562324d2..c8f18475 100644 --- a/app/views/dogs/show.html.erb +++ b/app/views/dogs/show.html.erb @@ -1,11 +1,26 @@
-

<%= @dog.name %>

+

<%= @dog.name %>

+ +
+ + +
+ +
+ + + +
+ + + +

<%= @dog.name %> has <%= @dog.likes.count %> likes! BARK!

<% @dog.images.each do |image| %> <%= image_tag url_for(image), alt: "Photo of #{@dog.name}" %> <% end %> -

<%= @dog.description %>

+

<%= @dog.description %>

<%= link_to "Edit #{@dog.name}'s Profile", edit_dog_path %>
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index d4bfefcd..25a6a169 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -1,10 +1,11 @@ - DogProfile + PDC DogProfile <%= csrf_meta_tags %> <%= csp_meta_tag %> + <%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track": "reload" %> <%= javascript_include_tag "application", "data-turbolinks-track": "reload" %> diff --git a/config/routes.rb b/config/routes.rb index 06b01adc..598038ca 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,6 +1,8 @@ Rails.application.routes.draw do # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html devise_for :users - resources :dogs + resources :dogs do + resources :likes, only: [:create, :destroy] + end root to: "dogs#index" end diff --git a/db/migrate/20190228172840_create_likes.rb b/db/migrate/20190228172840_create_likes.rb new file mode 100644 index 00000000..82ba9e18 --- /dev/null +++ b/db/migrate/20190228172840_create_likes.rb @@ -0,0 +1,9 @@ +class CreateLikes < ActiveRecord::Migration[5.2] + def change + create_table :likes do |t| + t.integer :user_id + t.integer :dog_id + t.timestamps + end + end +end diff --git a/db/migrate/20190228172909_add_user_to_dogs.rb b/db/migrate/20190228172909_add_user_to_dogs.rb new file mode 100644 index 00000000..6b393bbe --- /dev/null +++ b/db/migrate/20190228172909_add_user_to_dogs.rb @@ -0,0 +1,5 @@ +class AddUserToDogs < ActiveRecord::Migration[5.2] + def change + add_column :dogs, :user_id, :integer + end +end diff --git a/db/schema.rb b/db/schema.rb index 462bd430..f1f11dd3 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: 2018_06_07_114248) do +ActiveRecord::Schema.define(version: 2019_02_28_172909) do create_table "active_storage_attachments", force: :cascade do |t| t.string "name", null: false @@ -40,6 +40,14 @@ t.text "description" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.integer "user_id" + end + + create_table "likes", force: :cascade do |t| + t.integer "user_id" + t.integer "dog_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false end create_table "users", force: :cascade do |t|