Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ group :development, :test do
gem 'capybara'
gem 'pry'
gem 'rails-controller-testing'
gem 'faker'
end

group :development do
Expand Down
5 changes: 4 additions & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ GEM
factory_bot_rails (1.0.0.alpha)
factory_bot (~> 1.0.0.alpha)
railties (>= 3.0.0)
faker (2.2.1)
i18n (>= 0.8)
ffi (1.9.25)
globalid (0.4.1)
activesupport (>= 4.2.0)
Expand Down Expand Up @@ -233,6 +235,7 @@ DEPENDENCIES
coffee-rails (~> 4.2)
devise
factory_bot_rails
faker
jbuilder (~> 2.5)
listen (>= 3.0.5, < 3.2)
pry
Expand All @@ -254,4 +257,4 @@ RUBY VERSION
ruby 2.4.4p296

BUNDLED WITH
1.16.2
2.1.4
22 changes: 20 additions & 2 deletions app/controllers/dogs_controller.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
class DogsController < ApplicationController
before_action :set_dog, only: [:show, :edit, :update, :destroy]
before_action :set_dogs, only: %i[index]
before_action :set_dog, only: %i[show edit update destroy]
before_action :redirect_unless_can_update, only: %i[edit update destroy]

# GET /dogs
# GET /dogs.json
def index
@dogs = Dog.all
end

# GET /dogs/1
Expand Down Expand Up @@ -75,4 +76,21 @@ def set_dog
def dog_params
params.require(:dog).permit(:name, :description, :images)
end

def redirect_unless_can_update
unless current_user.owner_of?(@dog)
flash[:notice] = "Oops you can't do that"
redirect_to dog_path(@dog)
end
end

def set_dogs
if params[:sort]
scope = params[:sort]
else
scope = :all
end

@dogs = Dog.send(scope)
end
end
28 changes: 28 additions & 0 deletions app/controllers/likes_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
class LikesController < ApplicationController
before_action :set_dog, only: %i[create destroy]

def create
like = @dog.likes.where(user_id: current_user.id).first_or_initialize

respond_to do |format|
if like.save
format.js { render :create }
else
format.json { render json: { errors: like.errors }, status: :unprocessable_entity }
end
end
end

def destroy
@dog.likes.where(user_id: current_user.id).destroy_all

respond_to do |format|
format.js { render :destroy }
end
end

private
def set_dog
@dog = Dog.find(params[:dog_id])
end
end
18 changes: 18 additions & 0 deletions app/helpers/users_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module UsersHelper
def can_edit?(dog)
logged_in? &&
current_user.owner_of?(dog)
end

def can_like?(dog)
logged_in? &&
!current_user.owner_of?(dog)
end

private

def logged_in?
current_user.present?
end
end

5 changes: 5 additions & 0 deletions app/models/dog.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
class Dog < ApplicationRecord
has_many_attached :images
has_many :likes
belongs_to :user

# TODO: Still needs ordering by recent likes (in the last hour)
scope :recent_likes, -> { order("likes_count DESC") }
end
4 changes: 4 additions & 0 deletions app/models/like.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
class Like < ApplicationRecord
belongs_to :dog, counter_cache: true
belongs_to :user
end
11 changes: 11 additions & 0 deletions app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,15 @@ class User < ApplicationRecord
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable

has_many :dogs
has_many :likes

def owner_of?(dog)
id == dog.user_id
end

def likes?(dog)
dog.likes.where(user_id: id).any?
end
end
9 changes: 9 additions & 0 deletions app/views/dogs/_likes.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<% if can_like?(dog) %>
<% if current_user.likes?(dog) %>
<%= link_to "Unlike", dog_like_path(dog), method: :delete, remote: true %>
<% else %>
<%= link_to "Like", dog_likes_path(dog), method: :post, remote: true %>
<% end %>
<% end %>

<p>Likes: <%= dog.likes.count %></p>
19 changes: 13 additions & 6 deletions app/views/dogs/_thumbnail.html.erb
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
<a href="<%= url_for(dog) %>">
<article>
<h2 class="dog-name"><%= dog.name %></h2>
<%= image_tag url_for(dog.images.first), class: "dog-photo", alt: "Photo of #{dog.name}" %>
</article>
</a>
<% if (dog_counter + 1) % 3 == 0 %>
<%= render "shared/ad" %>
<% else %>
<a href="<%= url_for(dog) %>">
<article>
<h2 class="dog-name"><%= dog.name %></h2>
<div id="dog_<%= dog.id %>_likes">
<%= render "dogs/likes", dog: dog %>
</div>
<%= image_tag url_for(dog.images.first), class: "dog-photo", alt: "Photo of #{dog.name}" %>
</article>
</a>
<% end %>
5 changes: 5 additions & 0 deletions app/views/dogs/index.html.erb
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
<%= form_tag dogs_path, method: :get do %>
<%= radio_button_tag :sort, "recent_likes", params[:sort] == "recent_likes" ? true : false %>
<%= label_tag :sort_likes, "Most likes in the last hour" %>
<%= submit_tag "Sort" %>
<% end %>
<%= render partial: 'thumbnail', collection: @dogs, as: :dog %>
12 changes: 9 additions & 3 deletions app/views/dogs/show.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@

<p><%= @dog.description %></p>

<%= link_to "Edit #{@dog.name}'s Profile", edit_dog_path %>
<br>
<%= link_to "Delete #{@dog.name}'s Profile", dog_path, method: :delete, data: { confirm: 'Are you sure?' } %>
<div id="dog_<%= @dog.id %>_likes">
<%= render "dogs/likes", dog: @dog %>
</div>

<% if can_edit?(@dog) %>
<%= link_to "Edit #{@dog.name}'s Profile", edit_dog_path %>
<br>
<%= link_to "Delete #{@dog.name}'s Profile", dog_path, method: :delete, data: { confirm: 'Are you sure?' } %>
<% end %>
</section>
3 changes: 3 additions & 0 deletions app/views/likes/create.js.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
document
.getElementById("dog_<%= @dog.id %>_likes")
.innerHTML = "<%= j render partial: "dogs/likes", locals: { dog: @dog } %>";
3 changes: 3 additions & 0 deletions app/views/likes/destroy.js.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
document
.getElementById("dog_<%= @dog.id %>_likes")
.innerHTML = "<%= j render partial: "dogs/likes", locals: { dog: @dog } %>";
1 change: 1 addition & 0 deletions app/views/shared/_ad.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<%= image_tag("ad.jpg") %>
5 changes: 4 additions & 1 deletion config/routes.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
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: %i[create]
delete "/:dog_id", to: "likes#destroy", as: :like
end
root to: "dogs#index"
end
5 changes: 5 additions & 0 deletions db/migrate/20200825221745_add_user_to_dogs.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddUserToDogs < ActiveRecord::Migration[5.2]
def change
add_reference :dogs, :user, foreign_key: true
end
end
8 changes: 8 additions & 0 deletions db/migrate/20200826004158_create_likes.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class CreateLikes < ActiveRecord::Migration[5.2]
def change
create_table :likes do |t|
t.references :user, foreign_key: true
t.references :dog, foreign_key: true
end
end
end
5 changes: 5 additions & 0 deletions db/migrate/20200826022636_add_likes_count_to_dogs.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddLikesCountToDogs < ActiveRecord::Migration[5.2]
def change
add_column :dogs, :likes_count, :integer
end
end
5 changes: 5 additions & 0 deletions db/migrate/20200826023426_add_time_stamp_to_likes.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddTimeStampToLikes < ActiveRecord::Migration[5.2]
def change
add_timestamps :likes, null: false, default: Time.now
end
end
14 changes: 13 additions & 1 deletion db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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: 2020_08_26_023426) do

create_table "active_storage_attachments", force: :cascade do |t|
t.string "name", null: false
Expand Down Expand Up @@ -40,6 +40,18 @@
t.text "description"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "user_id"
t.integer "likes_count"
t.index ["user_id"], name: "index_dogs_on_user_id"
end

create_table "likes", force: :cascade do |t|
t.integer "user_id"
t.integer "dog_id"
t.datetime "created_at", default: "2020-08-26 02:36:39", null: false
t.datetime "updated_at", default: "2020-08-26 02:36:39", null: false
t.index ["dog_id"], name: "index_likes_on_dog_id"
t.index ["user_id"], name: "index_likes_on_user_id"
end

create_table "users", force: :cascade do |t|
Expand Down
7 changes: 6 additions & 1 deletion db/seeds.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
# movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }])
# Character.create(name: 'Luke', movie: movies.first)

Dog.destroy_all
User.destroy_all

dogs = [
{
name: 'Bowie',
Expand Down Expand Up @@ -49,8 +52,10 @@
},
]

5.times { FactoryBot.create(:user) }

dogs.each do |dog|
dog = Dog.find_or_create_by(name: dog[:name], description: dog[:description])
dog = Dog.find_or_create_by(name: dog[:name], description: dog[:description], user: User.all.sample)
directory_name = File.join(Rails.root, 'db', 'seed', "#{dog[:name].downcase}", "*")

Dir.glob(directory_name).each do |filename|
Expand Down
2 changes: 2 additions & 0 deletions spec/factories/dogs.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,7 @@
filename: 'bowie_toys.jpeg',
content_type: 'image/jpeg')
end

user { create :user }
end
end
6 changes: 6 additions & 0 deletions spec/factories/likes.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
FactoryBot.define do
factory :like do
user { create :user }
dog { create :dog }
end
end
6 changes: 6 additions & 0 deletions spec/factories/users.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
FactoryBot.define do
factory :user do
email { Faker::Internet.email }
password { Faker::Internet.password }
end
end
33 changes: 33 additions & 0 deletions spec/models/users_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
require "rails_helper"

describe User do
describe "#owner_of?" do
subject { user.owner_of? dog }

let(:user) { create :user }

context "when the user owns the dog" do
let(:dog) { create :dog, user: user }
it { is_expected.to be true }
end

context "when the dog belongs to another user" do
let(:dog) { create :dog, user: create(:user) }
it { is_expected.to be false }
end
end

describe "#likes?" do
subject { user.likes? dog }

let(:dog) { create(:dog) }
let(:user) { dog.user }

it { is_expected.to be false }

context "when a user has liked a dog" do
before { create :like, user: user, dog: dog }
it { is_expected.to be true }
end
end
end
1 change: 1 addition & 0 deletions spec/rails_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,5 @@
config.filter_rails_from_backtrace!
# arbitrary gems may also be filtered via:
# config.filter_gems_from_backtrace("gem name")
config.include Devise::Test::ControllerHelpers, type: :controller
end