From 646306a18764f4e81be3ed6a779ce699bccd6ce7 Mon Sep 17 00:00:00 2001
From: Maurius Hill <146677371+mauriushill@users.noreply.github.com>
Date: Wed, 28 Feb 2024 21:39:26 +0000
Subject: [PATCH 01/24] install devise and add root
---
Gemfile | 2 +
Gemfile.lock | 14 ++
config/initializers/devise.rb | 313 ++++++++++++++++++++++++++++++++++
config/locales/devise.en.yml | 65 +++++++
config/routes.rb | 2 +-
5 files changed, 395 insertions(+), 1 deletion(-)
create mode 100644 config/initializers/devise.rb
create mode 100644 config/locales/devise.en.yml
diff --git a/Gemfile b/Gemfile
index bc0213aa6..e67ad0b29 100644
--- a/Gemfile
+++ b/Gemfile
@@ -3,6 +3,8 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" }
ruby "3.2.1"
+gem "devise"
+
gem "simple_form"
# Bundle edge Rails instead: gem "rails", github: "rails/rails", branch: "main"
diff --git a/Gemfile.lock b/Gemfile.lock
index a8196ad6f..21187bdf1 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -76,6 +76,7 @@ GEM
tabulo
awesome_print (1.9.2)
base64 (0.1.1)
+ bcrypt (3.1.20)
better_errors (2.9.1)
coderay (>= 1.0.0)
erubi (>= 1.0.0)
@@ -109,6 +110,12 @@ GEM
irb (>= 1.5.0)
reline (>= 0.3.1)
debug_inspector (1.1.0)
+ devise (4.9.3)
+ bcrypt (~> 3.0)
+ orm_adapter (~> 0.1)
+ railties (>= 4.1.0)
+ responders
+ warden (~> 1.2.3)
diff-lcs (1.5.0)
diffy (3.4.2)
domain_name (0.5.20190701)
@@ -215,6 +222,7 @@ GEM
faraday (>= 1, < 3)
sawyer (~> 0.9)
oj (3.13.23)
+ orm_adapter (0.5.0)
pg (1.4.6)
pry (0.14.2)
coderay (~> 1.1)
@@ -278,6 +286,9 @@ GEM
regexp_parser (2.8.2)
reline (0.3.9)
io-console (~> 0.5)
+ responders (3.1.1)
+ actionpack (>= 5.2)
+ railties (>= 5.2)
rexml (3.2.6)
rspec (3.12.0)
rspec-core (~> 3.12.0)
@@ -357,6 +368,8 @@ GEM
unf_ext
unf_ext (0.0.9.1)
unicode-display_width (2.4.2)
+ warden (1.2.9)
+ rack (>= 2.0.9)
web-console (4.2.1)
actionview (>= 6.0.0)
activemodel (>= 6.0.0)
@@ -398,6 +411,7 @@ DEPENDENCIES
bootsnap
capybara
debug
+ devise
dotenv-rails
draft_matchers
faker
diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb
new file mode 100644
index 000000000..f35e9b448
--- /dev/null
+++ b/config/initializers/devise.rb
@@ -0,0 +1,313 @@
+# frozen_string_literal: true
+
+# Assuming you have not yet modified this file, each configuration option below
+# is set to its default value. Note that some are commented out while others
+# are not: uncommented lines are intended to protect your configuration from
+# breaking changes in upgrades (i.e., in the event that future versions of
+# Devise change the default values for those options).
+#
+# Use this hook to configure devise mailer, warden hooks and so forth.
+# Many of these configuration options can be set straight in your model.
+Devise.setup do |config|
+ # The secret key used by Devise. Devise uses this key to generate
+ # random tokens. Changing this key will render invalid all existing
+ # confirmation, reset password and unlock tokens in the database.
+ # Devise will use the `secret_key_base` as its `secret_key`
+ # by default. You can change it below and use your own secret key.
+ # config.secret_key = '1195e9a32beda80520514abf5b9ab460c927cc0133103cde53b225b09c2f1d372467b3c4f425e7c48bb48921f76ddafc2354b7e6abb28b413489f8840508ec61'
+
+ # ==> Controller configuration
+ # Configure the parent class to the devise controllers.
+ # config.parent_controller = 'DeviseController'
+
+ # ==> Mailer Configuration
+ # Configure the e-mail address which will be shown in Devise::Mailer,
+ # note that it will be overwritten if you use your own mailer class
+ # with default "from" parameter.
+ config.mailer_sender = 'please-change-me-at-config-initializers-devise@example.com'
+
+ # Configure the class responsible to send e-mails.
+ # config.mailer = 'Devise::Mailer'
+
+ # Configure the parent class responsible to send e-mails.
+ # config.parent_mailer = 'ActionMailer::Base'
+
+ # ==> ORM configuration
+ # Load and configure the ORM. Supports :active_record (default) and
+ # :mongoid (bson_ext recommended) by default. Other ORMs may be
+ # available as additional gems.
+ require 'devise/orm/active_record'
+
+ # ==> Configuration for any authentication mechanism
+ # Configure which keys are used when authenticating a user. The default is
+ # just :email. You can configure it to use [:username, :subdomain], so for
+ # authenticating a user, both parameters are required. Remember that those
+ # parameters are used only when authenticating and not when retrieving from
+ # session. If you need permissions, you should implement that in a before filter.
+ # You can also supply a hash where the value is a boolean determining whether
+ # or not authentication should be aborted when the value is not present.
+ # config.authentication_keys = [:email]
+
+ # Configure parameters from the request object used for authentication. Each entry
+ # given should be a request method and it will automatically be passed to the
+ # find_for_authentication method and considered in your model lookup. For instance,
+ # if you set :request_keys to [:subdomain], :subdomain will be used on authentication.
+ # The same considerations mentioned for authentication_keys also apply to request_keys.
+ # config.request_keys = []
+
+ # Configure which authentication keys should be case-insensitive.
+ # These keys will be downcased upon creating or modifying a user and when used
+ # to authenticate or find a user. Default is :email.
+ config.case_insensitive_keys = [:email]
+
+ # Configure which authentication keys should have whitespace stripped.
+ # These keys will have whitespace before and after removed upon creating or
+ # modifying a user and when used to authenticate or find a user. Default is :email.
+ config.strip_whitespace_keys = [:email]
+
+ # Tell if authentication through request.params is enabled. True by default.
+ # It can be set to an array that will enable params authentication only for the
+ # given strategies, for example, `config.params_authenticatable = [:database]` will
+ # enable it only for database (email + password) authentication.
+ # config.params_authenticatable = true
+
+ # Tell if authentication through HTTP Auth is enabled. False by default.
+ # It can be set to an array that will enable http authentication only for the
+ # given strategies, for example, `config.http_authenticatable = [:database]` will
+ # enable it only for database authentication.
+ # For API-only applications to support authentication "out-of-the-box", you will likely want to
+ # enable this with :database unless you are using a custom strategy.
+ # The supported strategies are:
+ # :database = Support basic authentication with authentication key + password
+ # config.http_authenticatable = false
+
+ # If 401 status code should be returned for AJAX requests. True by default.
+ # config.http_authenticatable_on_xhr = true
+
+ # The realm used in Http Basic Authentication. 'Application' by default.
+ # config.http_authentication_realm = 'Application'
+
+ # It will change confirmation, password recovery and other workflows
+ # to behave the same regardless if the e-mail provided was right or wrong.
+ # Does not affect registerable.
+ # config.paranoid = true
+
+ # By default Devise will store the user in session. You can skip storage for
+ # particular strategies by setting this option.
+ # Notice that if you are skipping storage for all authentication paths, you
+ # may want to disable generating routes to Devise's sessions controller by
+ # passing skip: :sessions to `devise_for` in your config/routes.rb
+ config.skip_session_storage = [:http_auth]
+
+ # By default, Devise cleans up the CSRF token on authentication to
+ # avoid CSRF token fixation attacks. This means that, when using AJAX
+ # requests for sign in and sign up, you need to get a new CSRF token
+ # from the server. You can disable this option at your own risk.
+ # config.clean_up_csrf_token_on_authentication = true
+
+ # When false, Devise will not attempt to reload routes on eager load.
+ # This can reduce the time taken to boot the app but if your application
+ # requires the Devise mappings to be loaded during boot time the application
+ # won't boot properly.
+ # config.reload_routes = true
+
+ # ==> Configuration for :database_authenticatable
+ # For bcrypt, this is the cost for hashing the password and defaults to 12. If
+ # using other algorithms, it sets how many times you want the password to be hashed.
+ # The number of stretches used for generating the hashed password are stored
+ # with the hashed password. This allows you to change the stretches without
+ # invalidating existing passwords.
+ #
+ # Limiting the stretches to just one in testing will increase the performance of
+ # your test suite dramatically. However, it is STRONGLY RECOMMENDED to not use
+ # a value less than 10 in other environments. Note that, for bcrypt (the default
+ # algorithm), the cost increases exponentially with the number of stretches (e.g.
+ # a value of 20 is already extremely slow: approx. 60 seconds for 1 calculation).
+ config.stretches = Rails.env.test? ? 1 : 12
+
+ # Set up a pepper to generate the hashed password.
+ # config.pepper = '28644bc83ab709e7ee4fb687a6e196865ac010126becdbb7db5d388734c4abf586f09ca715d14840a5b0d2fa9dd6640f8e4aa4d6508d4dfddb3fbdaae3c263bd'
+
+ # Send a notification to the original email when the user's email is changed.
+ # config.send_email_changed_notification = false
+
+ # Send a notification email when the user's password is changed.
+ # config.send_password_change_notification = false
+
+ # ==> Configuration for :confirmable
+ # A period that the user is allowed to access the website even without
+ # confirming their account. For instance, if set to 2.days, the user will be
+ # able to access the website for two days without confirming their account,
+ # access will be blocked just in the third day.
+ # You can also set it to nil, which will allow the user to access the website
+ # without confirming their account.
+ # Default is 0.days, meaning the user cannot access the website without
+ # confirming their account.
+ # config.allow_unconfirmed_access_for = 2.days
+
+ # A period that the user is allowed to confirm their account before their
+ # token becomes invalid. For example, if set to 3.days, the user can confirm
+ # their account within 3 days after the mail was sent, but on the fourth day
+ # their account can't be confirmed with the token any more.
+ # Default is nil, meaning there is no restriction on how long a user can take
+ # before confirming their account.
+ # config.confirm_within = 3.days
+
+ # If true, requires any email changes to be confirmed (exactly the same way as
+ # initial account confirmation) to be applied. Requires additional unconfirmed_email
+ # db field (see migrations). Until confirmed, new email is stored in
+ # unconfirmed_email column, and copied to email column on successful confirmation.
+ config.reconfirmable = true
+
+ # Defines which key will be used when confirming an account
+ # config.confirmation_keys = [:email]
+
+ # ==> Configuration for :rememberable
+ # The time the user will be remembered without asking for credentials again.
+ # config.remember_for = 2.weeks
+
+ # Invalidates all the remember me tokens when the user signs out.
+ config.expire_all_remember_me_on_sign_out = true
+
+ # If true, extends the user's remember period when remembered via cookie.
+ # config.extend_remember_period = false
+
+ # Options to be passed to the created cookie. For instance, you can set
+ # secure: true in order to force SSL only cookies.
+ # config.rememberable_options = {}
+
+ # ==> Configuration for :validatable
+ # Range for password length.
+ config.password_length = 6..128
+
+ # Email regex used to validate email formats. It simply asserts that
+ # one (and only one) @ exists in the given string. This is mainly
+ # to give user feedback and not to assert the e-mail validity.
+ config.email_regexp = /\A[^@\s]+@[^@\s]+\z/
+
+ # ==> Configuration for :timeoutable
+ # The time you want to timeout the user session without activity. After this
+ # time the user will be asked for credentials again. Default is 30 minutes.
+ # config.timeout_in = 30.minutes
+
+ # ==> Configuration for :lockable
+ # Defines which strategy will be used to lock an account.
+ # :failed_attempts = Locks an account after a number of failed attempts to sign in.
+ # :none = No lock strategy. You should handle locking by yourself.
+ # config.lock_strategy = :failed_attempts
+
+ # Defines which key will be used when locking and unlocking an account
+ # config.unlock_keys = [:email]
+
+ # Defines which strategy will be used to unlock an account.
+ # :email = Sends an unlock link to the user email
+ # :time = Re-enables login after a certain amount of time (see :unlock_in below)
+ # :both = Enables both strategies
+ # :none = No unlock strategy. You should handle unlocking by yourself.
+ # config.unlock_strategy = :both
+
+ # Number of authentication tries before locking an account if lock_strategy
+ # is failed attempts.
+ # config.maximum_attempts = 20
+
+ # Time interval to unlock the account if :time is enabled as unlock_strategy.
+ # config.unlock_in = 1.hour
+
+ # Warn on the last attempt before the account is locked.
+ # config.last_attempt_warning = true
+
+ # ==> Configuration for :recoverable
+ #
+ # Defines which key will be used when recovering the password for an account
+ # config.reset_password_keys = [:email]
+
+ # Time interval you can reset your password with a reset password key.
+ # Don't put a too small interval or your users won't have the time to
+ # change their passwords.
+ config.reset_password_within = 6.hours
+
+ # When set to false, does not sign a user in automatically after their password is
+ # reset. Defaults to true, so a user is signed in automatically after a reset.
+ # config.sign_in_after_reset_password = true
+
+ # ==> Configuration for :encryptable
+ # Allow you to use another hashing or encryption algorithm besides bcrypt (default).
+ # You can use :sha1, :sha512 or algorithms from others authentication tools as
+ # :clearance_sha1, :authlogic_sha512 (then you should set stretches above to 20
+ # for default behavior) and :restful_authentication_sha1 (then you should set
+ # stretches to 10, and copy REST_AUTH_SITE_KEY to pepper).
+ #
+ # Require the `devise-encryptable` gem when using anything other than bcrypt
+ # config.encryptor = :sha512
+
+ # ==> Scopes configuration
+ # Turn scoped views on. Before rendering "sessions/new", it will first check for
+ # "users/sessions/new". It's turned off by default because it's slower if you
+ # are using only default views.
+ # config.scoped_views = false
+
+ # Configure the default scope given to Warden. By default it's the first
+ # devise role declared in your routes (usually :user).
+ # config.default_scope = :user
+
+ # Set this configuration to false if you want /users/sign_out to sign out
+ # only the current scope. By default, Devise signs out all scopes.
+ # config.sign_out_all_scopes = true
+
+ # ==> Navigation configuration
+ # Lists the formats that should be treated as navigational. Formats like
+ # :html should redirect to the sign in page when the user does not have
+ # access, but formats like :xml or :json, should return 401.
+ #
+ # If you have any extra navigational formats, like :iphone or :mobile, you
+ # should add them to the navigational formats lists.
+ #
+ # The "*/*" below is required to match Internet Explorer requests.
+ # config.navigational_formats = ['*/*', :html, :turbo_stream]
+
+ # The default HTTP method used to sign out a resource. Default is :delete.
+ config.sign_out_via = :delete
+
+ # ==> OmniAuth
+ # Add a new OmniAuth provider. Check the wiki for more information on setting
+ # up on your models and hooks.
+ # config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo'
+
+ # ==> Warden configuration
+ # If you want to use other strategies, that are not supported by Devise, or
+ # change the failure app, you can configure them inside the config.warden block.
+ #
+ # config.warden do |manager|
+ # manager.intercept_401 = false
+ # manager.default_strategies(scope: :user).unshift :some_external_strategy
+ # end
+
+ # ==> Mountable engine configurations
+ # When using Devise inside an engine, let's call it `MyEngine`, and this engine
+ # is mountable, there are some extra configurations to be taken into account.
+ # The following options are available, assuming the engine is mounted as:
+ #
+ # mount MyEngine, at: '/my_engine'
+ #
+ # The router that invoked `devise_for`, in the example above, would be:
+ # config.router_name = :my_engine
+ #
+ # When using OmniAuth, Devise cannot automatically set OmniAuth path,
+ # so you need to do it manually. For the users scope, it would be:
+ # config.omniauth_path_prefix = '/my_engine/users/auth'
+
+ # ==> Hotwire/Turbo configuration
+ # When using Devise with Hotwire/Turbo, the http status for error responses
+ # and some redirects must match the following. The default in Devise for existing
+ # apps is `200 OK` and `302 Found` respectively, but new apps are generated with
+ # these new defaults that match Hotwire/Turbo behavior.
+ # Note: These might become the new default in future versions of Devise.
+ config.responder.error_status = :unprocessable_entity
+ config.responder.redirect_status = :see_other
+
+ # ==> Configuration for :registerable
+
+ # When set to false, does not sign a user in automatically after their password is
+ # changed. Defaults to true, so a user is signed in automatically after changing a password.
+ # config.sign_in_after_change_password = true
+end
diff --git a/config/locales/devise.en.yml b/config/locales/devise.en.yml
new file mode 100644
index 000000000..260e1c4ba
--- /dev/null
+++ b/config/locales/devise.en.yml
@@ -0,0 +1,65 @@
+# Additional translations at https://github.com/heartcombo/devise/wiki/I18n
+
+en:
+ devise:
+ confirmations:
+ confirmed: "Your email address has been successfully confirmed."
+ send_instructions: "You will receive an email with instructions for how to confirm your email address in a few minutes."
+ send_paranoid_instructions: "If your email address exists in our database, you will receive an email with instructions for how to confirm your email address in a few minutes."
+ failure:
+ already_authenticated: "You are already signed in."
+ inactive: "Your account is not activated yet."
+ invalid: "Invalid %{authentication_keys} or password."
+ locked: "Your account is locked."
+ last_attempt: "You have one more attempt before your account is locked."
+ not_found_in_database: "Invalid %{authentication_keys} or password."
+ timeout: "Your session expired. Please sign in again to continue."
+ unauthenticated: "You need to sign in or sign up before continuing."
+ unconfirmed: "You have to confirm your email address before continuing."
+ mailer:
+ confirmation_instructions:
+ subject: "Confirmation instructions"
+ reset_password_instructions:
+ subject: "Reset password instructions"
+ unlock_instructions:
+ subject: "Unlock instructions"
+ email_changed:
+ subject: "Email Changed"
+ password_change:
+ subject: "Password Changed"
+ omniauth_callbacks:
+ failure: "Could not authenticate you from %{kind} because \"%{reason}\"."
+ success: "Successfully authenticated from %{kind} account."
+ passwords:
+ no_token: "You can't access this page without coming from a password reset email. If you do come from a password reset email, please make sure you used the full URL provided."
+ send_instructions: "You will receive an email with instructions on how to reset your password in a few minutes."
+ send_paranoid_instructions: "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes."
+ updated: "Your password has been changed successfully. You are now signed in."
+ updated_not_active: "Your password has been changed successfully."
+ registrations:
+ destroyed: "Bye! Your account has been successfully cancelled. We hope to see you again soon."
+ signed_up: "Welcome! You have signed up successfully."
+ signed_up_but_inactive: "You have signed up successfully. However, we could not sign you in because your account is not yet activated."
+ signed_up_but_locked: "You have signed up successfully. However, we could not sign you in because your account is locked."
+ signed_up_but_unconfirmed: "A message with a confirmation link has been sent to your email address. Please follow the link to activate your account."
+ update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and follow the confirmation link to confirm your new email address."
+ updated: "Your account has been updated successfully."
+ updated_but_not_signed_in: "Your account has been updated successfully, but since your password was changed, you need to sign in again."
+ sessions:
+ signed_in: "Signed in successfully."
+ signed_out: "Signed out successfully."
+ already_signed_out: "Signed out successfully."
+ unlocks:
+ send_instructions: "You will receive an email with instructions for how to unlock your account in a few minutes."
+ send_paranoid_instructions: "If your account exists, you will receive an email with instructions for how to unlock it in a few minutes."
+ unlocked: "Your account has been unlocked successfully. Please sign in to continue."
+ errors:
+ messages:
+ already_confirmed: "was already confirmed, please try signing in"
+ confirmation_period_expired: "needs to be confirmed within %{period}, please request a new one"
+ expired: "has expired, please request a new one"
+ not_found: "not found"
+ not_locked: "was not locked"
+ not_saved:
+ one: "1 error prohibited this %{resource} from being saved:"
+ other: "%{count} errors prohibited this %{resource} from being saved:"
diff --git a/config/routes.rb b/config/routes.rb
index 262ffd547..5b7f5f751 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -2,5 +2,5 @@
# Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
# Defines the root path route ("/")
- # root "articles#index"
+ root "photos#index"
end
From da83c7bc8cad283bc2474c2ed5c12c3a5d059e08 Mon Sep 17 00:00:00 2001
From: Maurius Hill <146677371+mauriushill@users.noreply.github.com>
Date: Wed, 28 Feb 2024 21:48:10 +0000
Subject: [PATCH 02/24] generated users with devise
---
app/models/user.rb | 6 +++
config/routes.rb | 1 +
.../20240228214549_devise_create_users.rb | 48 +++++++++++++++++++
3 files changed, 55 insertions(+)
create mode 100644 app/models/user.rb
create mode 100644 db/migrate/20240228214549_devise_create_users.rb
diff --git a/app/models/user.rb b/app/models/user.rb
new file mode 100644
index 000000000..47567994e
--- /dev/null
+++ b/app/models/user.rb
@@ -0,0 +1,6 @@
+class User < ApplicationRecord
+ # Include default devise modules. Others available are:
+ # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
+ devise :database_authenticatable, :registerable,
+ :recoverable, :rememberable, :validatable
+end
diff --git a/config/routes.rb b/config/routes.rb
index 5b7f5f751..84e0c02d1 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,4 +1,5 @@
Rails.application.routes.draw do
+ devise_for :users
# Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
# Defines the root path route ("/")
diff --git a/db/migrate/20240228214549_devise_create_users.rb b/db/migrate/20240228214549_devise_create_users.rb
new file mode 100644
index 000000000..f2f7b28c3
--- /dev/null
+++ b/db/migrate/20240228214549_devise_create_users.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+class DeviseCreateUsers < ActiveRecord::Migration[7.0]
+ def change
+ create_table :users do |t|
+ ## Database authenticatable
+ t.string :email, null: false, default: ""
+ t.string :encrypted_password, null: false, default: ""
+
+ ## Recoverable
+ t.string :reset_password_token
+ t.datetime :reset_password_sent_at
+
+ ## Rememberable
+ t.datetime :remember_created_at
+
+ ## Trackable
+ # t.integer :sign_in_count, default: 0, null: false
+ # t.datetime :current_sign_in_at
+ # t.datetime :last_sign_in_at
+ # t.string :current_sign_in_ip
+ # t.string :last_sign_in_ip
+
+ ## Confirmable
+ # t.string :confirmation_token
+ # t.datetime :confirmed_at
+ # t.datetime :confirmation_sent_at
+ # t.string :unconfirmed_email # Only if using reconfirmable
+
+ ## Lockable
+ # t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
+ # t.string :unlock_token # Only if unlock strategy is :email or :both
+ # t.datetime :locked_at
+
+ t.string :username
+ t.boolean :private
+ t.integer :likes_count
+ t.integer :comments_count
+
+ t.timestamps null: false
+ end
+
+ add_index :users, :email, unique: true
+ add_index :users, :reset_password_token, unique: true
+ # add_index :users, :confirmation_token, unique: true
+ # add_index :users, :unlock_token, unique: true
+ end
+end
From 2a6c84d55d290be6f0bae2dbaf38c6eedcad8ad1 Mon Sep 17 00:00:00 2001
From: Maurius Hill <146677371+mauriushill@users.noreply.github.com>
Date: Wed, 28 Feb 2024 22:02:10 +0000
Subject: [PATCH 03/24] edited and migrated devise users.
---
app/models/user.rb | 23 +++++++++++++++++++
.../20240228214549_devise_create_users.rb | 11 +++++----
db/schema.rb | 20 +++++++++++++++-
3 files changed, 49 insertions(+), 5 deletions(-)
diff --git a/app/models/user.rb b/app/models/user.rb
index 47567994e..4ee2015c2 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -1,3 +1,26 @@
+# == Schema Information
+#
+# Table name: users
+#
+# id :bigint not null, primary key
+# comments_count :integer default(0)
+# email :citext default(""), not null
+# encrypted_password :string default(""), not null
+# likes_count :integer default(0)
+# private :boolean
+# remember_created_at :datetime
+# reset_password_sent_at :datetime
+# reset_password_token :string
+# username :citext
+# created_at :datetime not null
+# updated_at :datetime not null
+#
+# Indexes
+#
+# index_users_on_email (email) UNIQUE
+# index_users_on_reset_password_token (reset_password_token) UNIQUE
+# index_users_on_username (username) UNIQUE
+#
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
diff --git a/db/migrate/20240228214549_devise_create_users.rb b/db/migrate/20240228214549_devise_create_users.rb
index f2f7b28c3..65d9444a3 100644
--- a/db/migrate/20240228214549_devise_create_users.rb
+++ b/db/migrate/20240228214549_devise_create_users.rb
@@ -3,8 +3,9 @@
class DeviseCreateUsers < ActiveRecord::Migration[7.0]
def change
create_table :users do |t|
+ enable_extension("citext")
## Database authenticatable
- t.string :email, null: false, default: ""
+ t.citext :email, null: false, default: ""
t.string :encrypted_password, null: false, default: ""
## Recoverable
@@ -32,10 +33,10 @@ def change
# t.string :unlock_token # Only if unlock strategy is :email or :both
# t.datetime :locked_at
- t.string :username
+ t.citext :username
t.boolean :private
- t.integer :likes_count
- t.integer :comments_count
+ t.integer :likes_count, default: 0
+ t.integer :comments_count, default: 0
t.timestamps null: false
end
@@ -44,5 +45,7 @@ def change
add_index :users, :reset_password_token, unique: true
# add_index :users, :confirmation_token, unique: true
# add_index :users, :unlock_token, unique: true
+ add_index :users, :username, unique: true
+
end
end
diff --git a/db/schema.rb b/db/schema.rb
index b783f9866..c77531187 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,8 +10,26 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema[7.0].define(version: 0) do
+ActiveRecord::Schema[7.0].define(version: 2024_02_28_214549) do
# These are extensions that must be enabled in order to support this database
+ enable_extension "citext"
enable_extension "plpgsql"
+ create_table "users", force: :cascade do |t|
+ t.citext "email", default: "", null: false
+ t.string "encrypted_password", default: "", null: false
+ t.string "reset_password_token"
+ t.datetime "reset_password_sent_at"
+ t.datetime "remember_created_at"
+ t.citext "username"
+ t.boolean "private"
+ t.integer "likes_count", default: 0
+ t.integer "comments_count", default: 0
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ t.index ["email"], name: "index_users_on_email", unique: true
+ t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
+ t.index ["username"], name: "index_users_on_username", unique: true
+ end
+
end
From 1caf265b295eb16e95b96db5e781d0a249421a6b Mon Sep 17 00:00:00 2001
From: Maurius Hill <146677371+mauriushill@users.noreply.github.com>
Date: Wed, 28 Feb 2024 22:21:02 +0000
Subject: [PATCH 04/24] generated photos.
---
app/controllers/photos_controller.rb | 70 ++++++++++++++++++++++
app/models/photo.rb | 3 +
app/models/user.rb | 2 +
app/views/photos/_form.html.erb | 42 +++++++++++++
app/views/photos/_photo.html.erb | 27 +++++++++
app/views/photos/_photo.json.jbuilder | 2 +
app/views/photos/edit.html.erb | 10 ++++
app/views/photos/index.html.erb | 14 +++++
app/views/photos/index.json.jbuilder | 1 +
app/views/photos/new.html.erb | 9 +++
app/views/photos/show.html.erb | 10 ++++
app/views/photos/show.json.jbuilder | 1 +
config/routes.rb | 1 +
db/migrate/20240228220903_create_photos.rb | 13 ++++
db/schema.rb | 14 ++++-
15 files changed, 218 insertions(+), 1 deletion(-)
create mode 100644 app/controllers/photos_controller.rb
create mode 100644 app/models/photo.rb
create mode 100644 app/views/photos/_form.html.erb
create mode 100644 app/views/photos/_photo.html.erb
create mode 100644 app/views/photos/_photo.json.jbuilder
create mode 100644 app/views/photos/edit.html.erb
create mode 100644 app/views/photos/index.html.erb
create mode 100644 app/views/photos/index.json.jbuilder
create mode 100644 app/views/photos/new.html.erb
create mode 100644 app/views/photos/show.html.erb
create mode 100644 app/views/photos/show.json.jbuilder
create mode 100644 db/migrate/20240228220903_create_photos.rb
diff --git a/app/controllers/photos_controller.rb b/app/controllers/photos_controller.rb
new file mode 100644
index 000000000..86ba2de13
--- /dev/null
+++ b/app/controllers/photos_controller.rb
@@ -0,0 +1,70 @@
+class PhotosController < ApplicationController
+ before_action :set_photo, only: %i[ show edit update destroy ]
+
+ # GET /photos or /photos.json
+ def index
+ @photos = Photo.all
+ end
+
+ # GET /photos/1 or /photos/1.json
+ def show
+ end
+
+ # GET /photos/new
+ def new
+ @photo = Photo.new
+ end
+
+ # GET /photos/1/edit
+ def edit
+ end
+
+ # POST /photos or /photos.json
+ def create
+ @photo = Photo.new(photo_params)
+
+ respond_to do |format|
+ if @photo.save
+ format.html { redirect_to photo_url(@photo), notice: "Photo was successfully created." }
+ format.json { render :show, status: :created, location: @photo }
+ else
+ format.html { render :new, status: :unprocessable_entity }
+ format.json { render json: @photo.errors, status: :unprocessable_entity }
+ end
+ end
+ end
+
+ # PATCH/PUT /photos/1 or /photos/1.json
+ def update
+ respond_to do |format|
+ if @photo.update(photo_params)
+ format.html { redirect_to photo_url(@photo), notice: "Photo was successfully updated." }
+ format.json { render :show, status: :ok, location: @photo }
+ else
+ format.html { render :edit, status: :unprocessable_entity }
+ format.json { render json: @photo.errors, status: :unprocessable_entity }
+ end
+ end
+ end
+
+ # DELETE /photos/1 or /photos/1.json
+ def destroy
+ @photo.destroy
+
+ respond_to do |format|
+ format.html { redirect_to photos_url, notice: "Photo was successfully destroyed." }
+ format.json { head :no_content }
+ end
+ end
+
+ private
+ # Use callbacks to share common setup or constraints between actions.
+ def set_photo
+ @photo = Photo.find(params[:id])
+ end
+
+ # Only allow a list of trusted parameters through.
+ def photo_params
+ params.require(:photo).permit(:image, :comments_count, :likes_count, :caption, :owner_id)
+ end
+end
diff --git a/app/models/photo.rb b/app/models/photo.rb
new file mode 100644
index 000000000..d8c703a0b
--- /dev/null
+++ b/app/models/photo.rb
@@ -0,0 +1,3 @@
+class Photo < ApplicationRecord
+ belongs_to :owner, class_name "User"
+end
diff --git a/app/models/user.rb b/app/models/user.rb
index 4ee2015c2..4f6f85014 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -26,4 +26,6 @@ class User < ApplicationRecord
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
+
+ has_many :own_photos, class_name: "Photo", foreign_key: "owner_id"
end
diff --git a/app/views/photos/_form.html.erb b/app/views/photos/_form.html.erb
new file mode 100644
index 000000000..2524df8e1
--- /dev/null
+++ b/app/views/photos/_form.html.erb
@@ -0,0 +1,42 @@
+<%= form_with(model: photo) do |form| %>
+ <% if photo.errors.any? %>
+
+
<%= pluralize(photo.errors.count, "error") %> prohibited this photo from being saved:
+
+
+ <% photo.errors.each do |error| %>
+ - <%= error.full_message %>
+ <% end %>
+
+
+ <% end %>
+
+
+ <%= form.label :image, style: "display: block" %>
+ <%= form.text_field :image %>
+
+
+
+ <%= form.label :comments_count, style: "display: block" %>
+ <%= form.number_field :comments_count %>
+
+
+
+ <%= form.label :likes_count, style: "display: block" %>
+ <%= form.number_field :likes_count %>
+
+
+
+ <%= form.label :caption, style: "display: block" %>
+ <%= form.text_area :caption %>
+
+
+
+ <%= form.label :owner_id, style: "display: block" %>
+ <%= form.text_field :owner_id %>
+
+
+
+ <%= form.submit %>
+
+<% end %>
diff --git a/app/views/photos/_photo.html.erb b/app/views/photos/_photo.html.erb
new file mode 100644
index 000000000..163412972
--- /dev/null
+++ b/app/views/photos/_photo.html.erb
@@ -0,0 +1,27 @@
+
+
+ Image:
+ <%= photo.image %>
+
+
+
+ Comments count:
+ <%= photo.comments_count %>
+
+
+
+ Likes count:
+ <%= photo.likes_count %>
+
+
+
+ Caption:
+ <%= photo.caption %>
+
+
+
+ Owner:
+ <%= photo.owner_id %>
+
+
+
diff --git a/app/views/photos/_photo.json.jbuilder b/app/views/photos/_photo.json.jbuilder
new file mode 100644
index 000000000..fad93a0a9
--- /dev/null
+++ b/app/views/photos/_photo.json.jbuilder
@@ -0,0 +1,2 @@
+json.extract! photo, :id, :image, :comments_count, :likes_count, :caption, :owner_id, :created_at, :updated_at
+json.url photo_url(photo, format: :json)
diff --git a/app/views/photos/edit.html.erb b/app/views/photos/edit.html.erb
new file mode 100644
index 000000000..334e57176
--- /dev/null
+++ b/app/views/photos/edit.html.erb
@@ -0,0 +1,10 @@
+Editing photo
+
+<%= render "form", photo: @photo %>
+
+
+
+
+ <%= link_to "Show this photo", @photo %> |
+ <%= link_to "Back to photos", photos_path %>
+
diff --git a/app/views/photos/index.html.erb b/app/views/photos/index.html.erb
new file mode 100644
index 000000000..bfcfea758
--- /dev/null
+++ b/app/views/photos/index.html.erb
@@ -0,0 +1,14 @@
+<%= notice %>
+
+Photos
+
+
+ <% @photos.each do |photo| %>
+ <%= render photo %>
+
+ <%= link_to "Show this photo", photo %>
+
+ <% end %>
+
+
+<%= link_to "New photo", new_photo_path %>
diff --git a/app/views/photos/index.json.jbuilder b/app/views/photos/index.json.jbuilder
new file mode 100644
index 000000000..24d84b804
--- /dev/null
+++ b/app/views/photos/index.json.jbuilder
@@ -0,0 +1 @@
+json.array! @photos, partial: "photos/photo", as: :photo
diff --git a/app/views/photos/new.html.erb b/app/views/photos/new.html.erb
new file mode 100644
index 000000000..4649e7ad5
--- /dev/null
+++ b/app/views/photos/new.html.erb
@@ -0,0 +1,9 @@
+New photo
+
+<%= render "form", photo: @photo %>
+
+
+
+
+ <%= link_to "Back to photos", photos_path %>
+
diff --git a/app/views/photos/show.html.erb b/app/views/photos/show.html.erb
new file mode 100644
index 000000000..2d4f05255
--- /dev/null
+++ b/app/views/photos/show.html.erb
@@ -0,0 +1,10 @@
+<%= notice %>
+
+<%= render @photo %>
+
+
+ <%= link_to "Edit this photo", edit_photo_path(@photo) %> |
+ <%= link_to "Back to photos", photos_path %>
+
+ <%= button_to "Destroy this photo", @photo, method: :delete %>
+
diff --git a/app/views/photos/show.json.jbuilder b/app/views/photos/show.json.jbuilder
new file mode 100644
index 000000000..5c0f6ffc9
--- /dev/null
+++ b/app/views/photos/show.json.jbuilder
@@ -0,0 +1 @@
+json.partial! "photos/photo", photo: @photo
diff --git a/config/routes.rb b/config/routes.rb
index 84e0c02d1..ec631d731 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,4 +1,5 @@
Rails.application.routes.draw do
+ resources :photos
devise_for :users
# Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
diff --git a/db/migrate/20240228220903_create_photos.rb b/db/migrate/20240228220903_create_photos.rb
new file mode 100644
index 000000000..12cd88abe
--- /dev/null
+++ b/db/migrate/20240228220903_create_photos.rb
@@ -0,0 +1,13 @@
+class CreatePhotos < ActiveRecord::Migration[7.0]
+ def change
+ create_table :photos do |t|
+ t.string :image
+ t.integer :comments_count, default: 0
+ t.integer :likes_count, default: 0
+ t.text :caption
+ t.references :owner, null: false, foreign_key: { to_table: :users }
+
+ t.timestamps
+ end
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index c77531187..815250091 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,11 +10,22 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema[7.0].define(version: 2024_02_28_214549) do
+ActiveRecord::Schema[7.0].define(version: 2024_02_28_220903) do
# These are extensions that must be enabled in order to support this database
enable_extension "citext"
enable_extension "plpgsql"
+ create_table "photos", force: :cascade do |t|
+ t.string "image"
+ t.integer "comments_count", default: 0
+ t.integer "likes_count", default: 0
+ t.text "caption"
+ t.bigint "owner_id", null: false
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ t.index ["owner_id"], name: "index_photos_on_owner_id"
+ end
+
create_table "users", force: :cascade do |t|
t.citext "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
@@ -32,4 +43,5 @@
t.index ["username"], name: "index_users_on_username", unique: true
end
+ add_foreign_key "photos", "users", column: "owner_id"
end
From 7ca395f99a5a1456347cefe372a087a7e214bec2 Mon Sep 17 00:00:00 2001
From: Maurius Hill <146677371+mauriushill@users.noreply.github.com>
Date: Wed, 28 Feb 2024 22:45:44 +0000
Subject: [PATCH 05/24] added colon to class name in the photo model.
---
app/models/photo.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/models/photo.rb b/app/models/photo.rb
index d8c703a0b..2cb4a3d8b 100644
--- a/app/models/photo.rb
+++ b/app/models/photo.rb
@@ -1,3 +1,3 @@
class Photo < ApplicationRecord
- belongs_to :owner, class_name "User"
+ belongs_to :owner, class_name: "User"
end
From b5ccf6c713fbc36e3f10e829e09c732183503942 Mon Sep 17 00:00:00 2001
From: Maurius Hill <146677371+mauriushill@users.noreply.github.com>
Date: Thu, 29 Feb 2024 18:19:27 +0000
Subject: [PATCH 06/24] Generated comments.
---
app/controllers/comments_controller.rb | 70 ++++++++++++++++++++
app/models/comment.rb | 24 +++++++
app/models/photo.rb | 22 ++++++
app/views/comments/_comment.html.erb | 17 +++++
app/views/comments/_comment.json.jbuilder | 2 +
app/views/comments/_form.html.erb | 32 +++++++++
app/views/comments/edit.html.erb | 10 +++
app/views/comments/index.html.erb | 14 ++++
app/views/comments/index.json.jbuilder | 1 +
app/views/comments/new.html.erb | 9 +++
app/views/comments/show.html.erb | 10 +++
app/views/comments/show.json.jbuilder | 1 +
config/routes.rb | 1 +
db/migrate/20240229181017_create_comments.rb | 11 +++
db/schema.rb | 13 +++-
15 files changed, 236 insertions(+), 1 deletion(-)
create mode 100644 app/controllers/comments_controller.rb
create mode 100644 app/models/comment.rb
create mode 100644 app/views/comments/_comment.html.erb
create mode 100644 app/views/comments/_comment.json.jbuilder
create mode 100644 app/views/comments/_form.html.erb
create mode 100644 app/views/comments/edit.html.erb
create mode 100644 app/views/comments/index.html.erb
create mode 100644 app/views/comments/index.json.jbuilder
create mode 100644 app/views/comments/new.html.erb
create mode 100644 app/views/comments/show.html.erb
create mode 100644 app/views/comments/show.json.jbuilder
create mode 100644 db/migrate/20240229181017_create_comments.rb
diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb
new file mode 100644
index 000000000..cd08b60c2
--- /dev/null
+++ b/app/controllers/comments_controller.rb
@@ -0,0 +1,70 @@
+class CommentsController < ApplicationController
+ before_action :set_comment, only: %i[ show edit update destroy ]
+
+ # GET /comments or /comments.json
+ def index
+ @comments = Comment.all
+ end
+
+ # GET /comments/1 or /comments/1.json
+ def show
+ end
+
+ # GET /comments/new
+ def new
+ @comment = Comment.new
+ end
+
+ # GET /comments/1/edit
+ def edit
+ end
+
+ # POST /comments or /comments.json
+ def create
+ @comment = Comment.new(comment_params)
+
+ respond_to do |format|
+ if @comment.save
+ format.html { redirect_to comment_url(@comment), notice: "Comment was successfully created." }
+ format.json { render :show, status: :created, location: @comment }
+ else
+ format.html { render :new, status: :unprocessable_entity }
+ format.json { render json: @comment.errors, status: :unprocessable_entity }
+ end
+ end
+ end
+
+ # PATCH/PUT /comments/1 or /comments/1.json
+ def update
+ respond_to do |format|
+ if @comment.update(comment_params)
+ format.html { redirect_to comment_url(@comment), notice: "Comment was successfully updated." }
+ format.json { render :show, status: :ok, location: @comment }
+ else
+ format.html { render :edit, status: :unprocessable_entity }
+ format.json { render json: @comment.errors, status: :unprocessable_entity }
+ end
+ end
+ end
+
+ # DELETE /comments/1 or /comments/1.json
+ def destroy
+ @comment.destroy
+
+ respond_to do |format|
+ format.html { redirect_to comments_url, notice: "Comment was successfully destroyed." }
+ format.json { head :no_content }
+ end
+ end
+
+ private
+ # Use callbacks to share common setup or constraints between actions.
+ def set_comment
+ @comment = Comment.find(params[:id])
+ end
+
+ # Only allow a list of trusted parameters through.
+ def comment_params
+ params.require(:comment).permit(:author_id, :photo_id, :body)
+ end
+end
diff --git a/app/models/comment.rb b/app/models/comment.rb
new file mode 100644
index 000000000..d2fb2066c
--- /dev/null
+++ b/app/models/comment.rb
@@ -0,0 +1,24 @@
+# == Schema Information
+#
+# Table name: comments
+#
+# id :bigint not null, primary key
+# body :text not null
+# created_at :datetime not null
+# updated_at :datetime not null
+# author_id :bigint not null
+# photo_id :bigint not null
+#
+# Indexes
+#
+# index_comments_on_photo_id (photo_id)
+#
+# Foreign Keys
+#
+# fk_rails_... (author_id => users.id)
+# fk_rails_... (photo_id => photos.id)
+#
+class Comment < ApplicationRecord
+ belongs_to :author, class_name: "User"
+ belongs_to :photo
+end
diff --git a/app/models/photo.rb b/app/models/photo.rb
index 2cb4a3d8b..83eee0759 100644
--- a/app/models/photo.rb
+++ b/app/models/photo.rb
@@ -1,3 +1,25 @@
+# == Schema Information
+#
+# Table name: photos
+#
+# id :bigint not null, primary key
+# caption :text
+# comments_count :integer default(0)
+# image :string
+# likes_count :integer default(0)
+# created_at :datetime not null
+# updated_at :datetime not null
+# owner_id :bigint not null
+#
+# Indexes
+#
+# index_photos_on_owner_id (owner_id)
+#
+# Foreign Keys
+#
+# fk_rails_... (owner_id => users.id)
+#
class Photo < ApplicationRecord
belongs_to :owner, class_name: "User"
+ has_many :comments
end
diff --git a/app/views/comments/_comment.html.erb b/app/views/comments/_comment.html.erb
new file mode 100644
index 000000000..e5aac46fe
--- /dev/null
+++ b/app/views/comments/_comment.html.erb
@@ -0,0 +1,17 @@
+
diff --git a/app/views/comments/_comment.json.jbuilder b/app/views/comments/_comment.json.jbuilder
new file mode 100644
index 000000000..64674aec1
--- /dev/null
+++ b/app/views/comments/_comment.json.jbuilder
@@ -0,0 +1,2 @@
+json.extract! comment, :id, :author_id, :photo_id, :body, :created_at, :updated_at
+json.url comment_url(comment, format: :json)
diff --git a/app/views/comments/_form.html.erb b/app/views/comments/_form.html.erb
new file mode 100644
index 000000000..15c64fa41
--- /dev/null
+++ b/app/views/comments/_form.html.erb
@@ -0,0 +1,32 @@
+<%= form_with(model: comment) do |form| %>
+ <% if comment.errors.any? %>
+
+
<%= pluralize(comment.errors.count, "error") %> prohibited this comment from being saved:
+
+
+ <% comment.errors.each do |error| %>
+ - <%= error.full_message %>
+ <% end %>
+
+
+ <% end %>
+
+
+ <%= form.label :author_id, style: "display: block" %>
+ <%= form.text_field :author_id %>
+
+
+
+ <%= form.label :photo_id, style: "display: block" %>
+ <%= form.text_field :photo_id %>
+
+
+
+ <%= form.label :body, style: "display: block" %>
+ <%= form.text_area :body %>
+
+
+
+ <%= form.submit %>
+
+<% end %>
diff --git a/app/views/comments/edit.html.erb b/app/views/comments/edit.html.erb
new file mode 100644
index 000000000..9720435b0
--- /dev/null
+++ b/app/views/comments/edit.html.erb
@@ -0,0 +1,10 @@
+Editing comment
+
+<%= render "form", comment: @comment %>
+
+
+
+
+ <%= link_to "Show this comment", @comment %> |
+ <%= link_to "Back to comments", comments_path %>
+
diff --git a/app/views/comments/index.html.erb b/app/views/comments/index.html.erb
new file mode 100644
index 000000000..c4935157a
--- /dev/null
+++ b/app/views/comments/index.html.erb
@@ -0,0 +1,14 @@
+<%= notice %>
+
+Comments
+
+
+
+<%= link_to "New comment", new_comment_path %>
diff --git a/app/views/comments/index.json.jbuilder b/app/views/comments/index.json.jbuilder
new file mode 100644
index 000000000..e3322af65
--- /dev/null
+++ b/app/views/comments/index.json.jbuilder
@@ -0,0 +1 @@
+json.array! @comments, partial: "comments/comment", as: :comment
diff --git a/app/views/comments/new.html.erb b/app/views/comments/new.html.erb
new file mode 100644
index 000000000..6ba6dd8a4
--- /dev/null
+++ b/app/views/comments/new.html.erb
@@ -0,0 +1,9 @@
+New comment
+
+<%= render "form", comment: @comment %>
+
+
+
+
+ <%= link_to "Back to comments", comments_path %>
+
diff --git a/app/views/comments/show.html.erb b/app/views/comments/show.html.erb
new file mode 100644
index 000000000..b90af0a6f
--- /dev/null
+++ b/app/views/comments/show.html.erb
@@ -0,0 +1,10 @@
+<%= notice %>
+
+<%= render @comment %>
+
+
+ <%= link_to "Edit this comment", edit_comment_path(@comment) %> |
+ <%= link_to "Back to comments", comments_path %>
+
+ <%= button_to "Destroy this comment", @comment, method: :delete %>
+
diff --git a/app/views/comments/show.json.jbuilder b/app/views/comments/show.json.jbuilder
new file mode 100644
index 000000000..78a9099a3
--- /dev/null
+++ b/app/views/comments/show.json.jbuilder
@@ -0,0 +1 @@
+json.partial! "comments/comment", comment: @comment
diff --git a/config/routes.rb b/config/routes.rb
index ec631d731..30f5cdb7f 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,4 +1,5 @@
Rails.application.routes.draw do
+ resources :comments
resources :photos
devise_for :users
# Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
diff --git a/db/migrate/20240229181017_create_comments.rb b/db/migrate/20240229181017_create_comments.rb
new file mode 100644
index 000000000..2e637126b
--- /dev/null
+++ b/db/migrate/20240229181017_create_comments.rb
@@ -0,0 +1,11 @@
+class CreateComments < ActiveRecord::Migration[7.0]
+ def change
+ create_table :comments do |t|
+ t.references :author, null: false, foreign_key: { to_table: :users }, index: false
+ t.references :photo, null: false, foreign_key: true
+ t.text :body, null: false
+
+ t.timestamps
+ end
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 815250091..85a89287a 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,11 +10,20 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema[7.0].define(version: 2024_02_28_220903) do
+ActiveRecord::Schema[7.0].define(version: 2024_02_29_181017) do
# These are extensions that must be enabled in order to support this database
enable_extension "citext"
enable_extension "plpgsql"
+ create_table "comments", force: :cascade do |t|
+ t.bigint "author_id", null: false
+ t.bigint "photo_id", null: false
+ t.text "body", null: false
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ t.index ["photo_id"], name: "index_comments_on_photo_id"
+ end
+
create_table "photos", force: :cascade do |t|
t.string "image"
t.integer "comments_count", default: 0
@@ -43,5 +52,7 @@
t.index ["username"], name: "index_users_on_username", unique: true
end
+ add_foreign_key "comments", "photos"
+ add_foreign_key "comments", "users", column: "author_id"
add_foreign_key "photos", "users", column: "owner_id"
end
From af75a3ce546022163dc665f7bb98191c36ebab8b Mon Sep 17 00:00:00 2001
From: Maurius Hill <146677371+mauriushill@users.noreply.github.com>
Date: Thu, 29 Feb 2024 18:28:19 +0000
Subject: [PATCH 07/24] Generated follow request.
---
app/controllers/follow_requests_controller.rb | 70 +++++++++++++++++++
app/models/follow_request.rb | 25 +++++++
.../follow_requests/_follow_request.html.erb | 17 +++++
.../_follow_request.json.jbuilder | 2 +
app/views/follow_requests/_form.html.erb | 32 +++++++++
app/views/follow_requests/edit.html.erb | 10 +++
app/views/follow_requests/index.html.erb | 14 ++++
app/views/follow_requests/index.json.jbuilder | 1 +
app/views/follow_requests/new.html.erb | 9 +++
app/views/follow_requests/show.html.erb | 10 +++
app/views/follow_requests/show.json.jbuilder | 1 +
config/routes.rb | 1 +
.../20240229182331_create_follow_requests.rb | 11 +++
db/schema.rb | 14 +++-
14 files changed, 216 insertions(+), 1 deletion(-)
create mode 100644 app/controllers/follow_requests_controller.rb
create mode 100644 app/models/follow_request.rb
create mode 100644 app/views/follow_requests/_follow_request.html.erb
create mode 100644 app/views/follow_requests/_follow_request.json.jbuilder
create mode 100644 app/views/follow_requests/_form.html.erb
create mode 100644 app/views/follow_requests/edit.html.erb
create mode 100644 app/views/follow_requests/index.html.erb
create mode 100644 app/views/follow_requests/index.json.jbuilder
create mode 100644 app/views/follow_requests/new.html.erb
create mode 100644 app/views/follow_requests/show.html.erb
create mode 100644 app/views/follow_requests/show.json.jbuilder
create mode 100644 db/migrate/20240229182331_create_follow_requests.rb
diff --git a/app/controllers/follow_requests_controller.rb b/app/controllers/follow_requests_controller.rb
new file mode 100644
index 000000000..47074cf0f
--- /dev/null
+++ b/app/controllers/follow_requests_controller.rb
@@ -0,0 +1,70 @@
+class FollowRequestsController < ApplicationController
+ before_action :set_follow_request, only: %i[ show edit update destroy ]
+
+ # GET /follow_requests or /follow_requests.json
+ def index
+ @follow_requests = FollowRequest.all
+ end
+
+ # GET /follow_requests/1 or /follow_requests/1.json
+ def show
+ end
+
+ # GET /follow_requests/new
+ def new
+ @follow_request = FollowRequest.new
+ end
+
+ # GET /follow_requests/1/edit
+ def edit
+ end
+
+ # POST /follow_requests or /follow_requests.json
+ def create
+ @follow_request = FollowRequest.new(follow_request_params)
+
+ respond_to do |format|
+ if @follow_request.save
+ format.html { redirect_to follow_request_url(@follow_request), notice: "Follow request was successfully created." }
+ format.json { render :show, status: :created, location: @follow_request }
+ else
+ format.html { render :new, status: :unprocessable_entity }
+ format.json { render json: @follow_request.errors, status: :unprocessable_entity }
+ end
+ end
+ end
+
+ # PATCH/PUT /follow_requests/1 or /follow_requests/1.json
+ def update
+ respond_to do |format|
+ if @follow_request.update(follow_request_params)
+ format.html { redirect_to follow_request_url(@follow_request), notice: "Follow request was successfully updated." }
+ format.json { render :show, status: :ok, location: @follow_request }
+ else
+ format.html { render :edit, status: :unprocessable_entity }
+ format.json { render json: @follow_request.errors, status: :unprocessable_entity }
+ end
+ end
+ end
+
+ # DELETE /follow_requests/1 or /follow_requests/1.json
+ def destroy
+ @follow_request.destroy
+
+ respond_to do |format|
+ format.html { redirect_to follow_requests_url, notice: "Follow request was successfully destroyed." }
+ format.json { head :no_content }
+ end
+ end
+
+ private
+ # Use callbacks to share common setup or constraints between actions.
+ def set_follow_request
+ @follow_request = FollowRequest.find(params[:id])
+ end
+
+ # Only allow a list of trusted parameters through.
+ def follow_request_params
+ params.require(:follow_request).permit(:recipient_id, :sender_id, :status)
+ end
+end
diff --git a/app/models/follow_request.rb b/app/models/follow_request.rb
new file mode 100644
index 000000000..b2f81264a
--- /dev/null
+++ b/app/models/follow_request.rb
@@ -0,0 +1,25 @@
+# == Schema Information
+#
+# Table name: follow_requests
+#
+# id :bigint not null, primary key
+# status :string default("pending")
+# created_at :datetime not null
+# updated_at :datetime not null
+# recipient_id :bigint not null
+# sender_id :bigint not null
+#
+# Indexes
+#
+# index_follow_requests_on_recipient_id (recipient_id)
+# index_follow_requests_on_sender_id (sender_id)
+#
+# Foreign Keys
+#
+# fk_rails_... (recipient_id => users.id)
+# fk_rails_... (sender_id => users.id)
+#
+class FollowRequest < ApplicationRecord
+ belongs_to :recipient, class_name: "User"
+ belongs_to :sender, class_name: "User"
+end
diff --git a/app/views/follow_requests/_follow_request.html.erb b/app/views/follow_requests/_follow_request.html.erb
new file mode 100644
index 000000000..3b9f8c078
--- /dev/null
+++ b/app/views/follow_requests/_follow_request.html.erb
@@ -0,0 +1,17 @@
+
+
+ Recipient:
+ <%= follow_request.recipient_id %>
+
+
+
+ Sender:
+ <%= follow_request.sender_id %>
+
+
+
+ Status:
+ <%= follow_request.status %>
+
+
+
diff --git a/app/views/follow_requests/_follow_request.json.jbuilder b/app/views/follow_requests/_follow_request.json.jbuilder
new file mode 100644
index 000000000..d7dd54cc5
--- /dev/null
+++ b/app/views/follow_requests/_follow_request.json.jbuilder
@@ -0,0 +1,2 @@
+json.extract! follow_request, :id, :recipient_id, :sender_id, :status, :created_at, :updated_at
+json.url follow_request_url(follow_request, format: :json)
diff --git a/app/views/follow_requests/_form.html.erb b/app/views/follow_requests/_form.html.erb
new file mode 100644
index 000000000..f32eef830
--- /dev/null
+++ b/app/views/follow_requests/_form.html.erb
@@ -0,0 +1,32 @@
+<%= form_with(model: follow_request) do |form| %>
+ <% if follow_request.errors.any? %>
+
+
<%= pluralize(follow_request.errors.count, "error") %> prohibited this follow_request from being saved:
+
+
+ <% follow_request.errors.each do |error| %>
+ - <%= error.full_message %>
+ <% end %>
+
+
+ <% end %>
+
+
+ <%= form.label :recipient_id, style: "display: block" %>
+ <%= form.text_field :recipient_id %>
+
+
+
+ <%= form.label :sender_id, style: "display: block" %>
+ <%= form.text_field :sender_id %>
+
+
+
+ <%= form.label :status, style: "display: block" %>
+ <%= form.text_field :status %>
+
+
+
+ <%= form.submit %>
+
+<% end %>
diff --git a/app/views/follow_requests/edit.html.erb b/app/views/follow_requests/edit.html.erb
new file mode 100644
index 000000000..7c42ec88d
--- /dev/null
+++ b/app/views/follow_requests/edit.html.erb
@@ -0,0 +1,10 @@
+Editing follow request
+
+<%= render "form", follow_request: @follow_request %>
+
+
+
+
+ <%= link_to "Show this follow request", @follow_request %> |
+ <%= link_to "Back to follow requests", follow_requests_path %>
+
diff --git a/app/views/follow_requests/index.html.erb b/app/views/follow_requests/index.html.erb
new file mode 100644
index 000000000..20fd53284
--- /dev/null
+++ b/app/views/follow_requests/index.html.erb
@@ -0,0 +1,14 @@
+<%= notice %>
+
+Follow requests
+
+
+ <% @follow_requests.each do |follow_request| %>
+ <%= render follow_request %>
+
+ <%= link_to "Show this follow request", follow_request %>
+
+ <% end %>
+
+
+<%= link_to "New follow request", new_follow_request_path %>
diff --git a/app/views/follow_requests/index.json.jbuilder b/app/views/follow_requests/index.json.jbuilder
new file mode 100644
index 000000000..b45255d0f
--- /dev/null
+++ b/app/views/follow_requests/index.json.jbuilder
@@ -0,0 +1 @@
+json.array! @follow_requests, partial: "follow_requests/follow_request", as: :follow_request
diff --git a/app/views/follow_requests/new.html.erb b/app/views/follow_requests/new.html.erb
new file mode 100644
index 000000000..f13075ef6
--- /dev/null
+++ b/app/views/follow_requests/new.html.erb
@@ -0,0 +1,9 @@
+New follow request
+
+<%= render "form", follow_request: @follow_request %>
+
+
+
+
+ <%= link_to "Back to follow requests", follow_requests_path %>
+
diff --git a/app/views/follow_requests/show.html.erb b/app/views/follow_requests/show.html.erb
new file mode 100644
index 000000000..6db53cce2
--- /dev/null
+++ b/app/views/follow_requests/show.html.erb
@@ -0,0 +1,10 @@
+<%= notice %>
+
+<%= render @follow_request %>
+
+
+ <%= link_to "Edit this follow request", edit_follow_request_path(@follow_request) %> |
+ <%= link_to "Back to follow requests", follow_requests_path %>
+
+ <%= button_to "Destroy this follow request", @follow_request, method: :delete %>
+
diff --git a/app/views/follow_requests/show.json.jbuilder b/app/views/follow_requests/show.json.jbuilder
new file mode 100644
index 000000000..3fb15c16d
--- /dev/null
+++ b/app/views/follow_requests/show.json.jbuilder
@@ -0,0 +1 @@
+json.partial! "follow_requests/follow_request", follow_request: @follow_request
diff --git a/config/routes.rb b/config/routes.rb
index 30f5cdb7f..9ca7ff2a0 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,4 +1,5 @@
Rails.application.routes.draw do
+ resources :follow_requests
resources :comments
resources :photos
devise_for :users
diff --git a/db/migrate/20240229182331_create_follow_requests.rb b/db/migrate/20240229182331_create_follow_requests.rb
new file mode 100644
index 000000000..499dabba1
--- /dev/null
+++ b/db/migrate/20240229182331_create_follow_requests.rb
@@ -0,0 +1,11 @@
+class CreateFollowRequests < ActiveRecord::Migration[7.0]
+ def change
+ create_table :follow_requests do |t|
+ t.references :recipient, null: false, foreign_key: { to_table: :users }
+ t.references :sender, null: false, foreign_key: { to_table: :users }
+ t.string :status, default: "pending"
+
+ t.timestamps
+ end
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 85a89287a..9d18ec4fd 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[7.0].define(version: 2024_02_29_181017) do
+ActiveRecord::Schema[7.0].define(version: 2024_02_29_182331) do
# These are extensions that must be enabled in order to support this database
enable_extension "citext"
enable_extension "plpgsql"
@@ -24,6 +24,16 @@
t.index ["photo_id"], name: "index_comments_on_photo_id"
end
+ create_table "follow_requests", force: :cascade do |t|
+ t.bigint "recipient_id", null: false
+ t.bigint "sender_id", null: false
+ t.string "status", default: "pending"
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ t.index ["recipient_id"], name: "index_follow_requests_on_recipient_id"
+ t.index ["sender_id"], name: "index_follow_requests_on_sender_id"
+ end
+
create_table "photos", force: :cascade do |t|
t.string "image"
t.integer "comments_count", default: 0
@@ -54,5 +64,7 @@
add_foreign_key "comments", "photos"
add_foreign_key "comments", "users", column: "author_id"
+ add_foreign_key "follow_requests", "users", column: "recipient_id"
+ add_foreign_key "follow_requests", "users", column: "sender_id"
add_foreign_key "photos", "users", column: "owner_id"
end
From c454348a8941ca553f389815606f59c4eae68854 Mon Sep 17 00:00:00 2001
From: Maurius Hill <146677371+mauriushill@users.noreply.github.com>
Date: Thu, 29 Feb 2024 19:09:21 +0000
Subject: [PATCH 08/24] Generated likes.
---
app/controllers/likes_controller.rb | 70 +++++++++++++++++++++++
app/models/like.rb | 24 ++++++++
app/views/likes/_form.html.erb | 27 +++++++++
app/views/likes/_like.html.erb | 12 ++++
app/views/likes/_like.json.jbuilder | 2 +
app/views/likes/edit.html.erb | 10 ++++
app/views/likes/index.html.erb | 14 +++++
app/views/likes/index.json.jbuilder | 1 +
app/views/likes/new.html.erb | 9 +++
app/views/likes/show.html.erb | 10 ++++
app/views/likes/show.json.jbuilder | 1 +
config/routes.rb | 1 +
db/migrate/20240229182950_create_likes.rb | 10 ++++
db/schema.rb | 13 ++++-
14 files changed, 203 insertions(+), 1 deletion(-)
create mode 100644 app/controllers/likes_controller.rb
create mode 100644 app/models/like.rb
create mode 100644 app/views/likes/_form.html.erb
create mode 100644 app/views/likes/_like.html.erb
create mode 100644 app/views/likes/_like.json.jbuilder
create mode 100644 app/views/likes/edit.html.erb
create mode 100644 app/views/likes/index.html.erb
create mode 100644 app/views/likes/index.json.jbuilder
create mode 100644 app/views/likes/new.html.erb
create mode 100644 app/views/likes/show.html.erb
create mode 100644 app/views/likes/show.json.jbuilder
create mode 100644 db/migrate/20240229182950_create_likes.rb
diff --git a/app/controllers/likes_controller.rb b/app/controllers/likes_controller.rb
new file mode 100644
index 000000000..f38a1c6e9
--- /dev/null
+++ b/app/controllers/likes_controller.rb
@@ -0,0 +1,70 @@
+class LikesController < ApplicationController
+ before_action :set_like, only: %i[ show edit update destroy ]
+
+ # GET /likes or /likes.json
+ def index
+ @likes = Like.all
+ end
+
+ # GET /likes/1 or /likes/1.json
+ def show
+ end
+
+ # GET /likes/new
+ def new
+ @like = Like.new
+ end
+
+ # GET /likes/1/edit
+ def edit
+ end
+
+ # POST /likes or /likes.json
+ def create
+ @like = Like.new(like_params)
+
+ respond_to do |format|
+ if @like.save
+ format.html { redirect_to like_url(@like), notice: "Like was successfully created." }
+ format.json { render :show, status: :created, location: @like }
+ else
+ format.html { render :new, status: :unprocessable_entity }
+ format.json { render json: @like.errors, status: :unprocessable_entity }
+ end
+ end
+ end
+
+ # PATCH/PUT /likes/1 or /likes/1.json
+ def update
+ respond_to do |format|
+ if @like.update(like_params)
+ format.html { redirect_to like_url(@like), notice: "Like was successfully updated." }
+ format.json { render :show, status: :ok, location: @like }
+ else
+ format.html { render :edit, status: :unprocessable_entity }
+ format.json { render json: @like.errors, status: :unprocessable_entity }
+ end
+ end
+ end
+
+ # DELETE /likes/1 or /likes/1.json
+ def destroy
+ @like.destroy
+
+ respond_to do |format|
+ format.html { redirect_to likes_url, notice: "Like was successfully destroyed." }
+ format.json { head :no_content }
+ end
+ end
+
+ private
+ # Use callbacks to share common setup or constraints between actions.
+ def set_like
+ @like = Like.find(params[:id])
+ end
+
+ # Only allow a list of trusted parameters through.
+ def like_params
+ params.require(:like).permit(:fan_id, :photo_id)
+ end
+end
diff --git a/app/models/like.rb b/app/models/like.rb
new file mode 100644
index 000000000..53806dcdd
--- /dev/null
+++ b/app/models/like.rb
@@ -0,0 +1,24 @@
+# == Schema Information
+#
+# Table name: likes
+#
+# id :bigint not null, primary key
+# created_at :datetime not null
+# updated_at :datetime not null
+# fan_id :bigint not null
+# photo_id :bigint not null
+#
+# Indexes
+#
+# index_likes_on_fan_id (fan_id)
+# index_likes_on_photo_id (photo_id)
+#
+# Foreign Keys
+#
+# fk_rails_... (fan_id => users.id)
+# fk_rails_... (photo_id => photos.id)
+#
+class Like < ApplicationRecord
+ belongs_to :fan, class_name: "User"
+ belongs_to :photo
+end
diff --git a/app/views/likes/_form.html.erb b/app/views/likes/_form.html.erb
new file mode 100644
index 000000000..29370e5f4
--- /dev/null
+++ b/app/views/likes/_form.html.erb
@@ -0,0 +1,27 @@
+<%= form_with(model: like) do |form| %>
+ <% if like.errors.any? %>
+
+
<%= pluralize(like.errors.count, "error") %> prohibited this like from being saved:
+
+
+ <% like.errors.each do |error| %>
+ - <%= error.full_message %>
+ <% end %>
+
+
+ <% end %>
+
+
+ <%= form.label :fan_id, style: "display: block" %>
+ <%= form.text_field :fan_id %>
+
+
+
+ <%= form.label :photo_id, style: "display: block" %>
+ <%= form.text_field :photo_id %>
+
+
+
+ <%= form.submit %>
+
+<% end %>
diff --git a/app/views/likes/_like.html.erb b/app/views/likes/_like.html.erb
new file mode 100644
index 000000000..f10d1d01a
--- /dev/null
+++ b/app/views/likes/_like.html.erb
@@ -0,0 +1,12 @@
+
+
+ Fan:
+ <%= like.fan_id %>
+
+
+
+ Photo:
+ <%= like.photo_id %>
+
+
+
diff --git a/app/views/likes/_like.json.jbuilder b/app/views/likes/_like.json.jbuilder
new file mode 100644
index 000000000..f89aea4a0
--- /dev/null
+++ b/app/views/likes/_like.json.jbuilder
@@ -0,0 +1,2 @@
+json.extract! like, :id, :fan_id, :photo_id, :created_at, :updated_at
+json.url like_url(like, format: :json)
diff --git a/app/views/likes/edit.html.erb b/app/views/likes/edit.html.erb
new file mode 100644
index 000000000..39beff900
--- /dev/null
+++ b/app/views/likes/edit.html.erb
@@ -0,0 +1,10 @@
+Editing like
+
+<%= render "form", like: @like %>
+
+
+
+
+ <%= link_to "Show this like", @like %> |
+ <%= link_to "Back to likes", likes_path %>
+
diff --git a/app/views/likes/index.html.erb b/app/views/likes/index.html.erb
new file mode 100644
index 000000000..3032ac648
--- /dev/null
+++ b/app/views/likes/index.html.erb
@@ -0,0 +1,14 @@
+<%= notice %>
+
+Likes
+
+
+ <% @likes.each do |like| %>
+ <%= render like %>
+
+ <%= link_to "Show this like", like %>
+
+ <% end %>
+
+
+<%= link_to "New like", new_like_path %>
diff --git a/app/views/likes/index.json.jbuilder b/app/views/likes/index.json.jbuilder
new file mode 100644
index 000000000..721d47627
--- /dev/null
+++ b/app/views/likes/index.json.jbuilder
@@ -0,0 +1 @@
+json.array! @likes, partial: "likes/like", as: :like
diff --git a/app/views/likes/new.html.erb b/app/views/likes/new.html.erb
new file mode 100644
index 000000000..706f8f9d8
--- /dev/null
+++ b/app/views/likes/new.html.erb
@@ -0,0 +1,9 @@
+New like
+
+<%= render "form", like: @like %>
+
+
+
+
+ <%= link_to "Back to likes", likes_path %>
+
diff --git a/app/views/likes/show.html.erb b/app/views/likes/show.html.erb
new file mode 100644
index 000000000..b635317e8
--- /dev/null
+++ b/app/views/likes/show.html.erb
@@ -0,0 +1,10 @@
+<%= notice %>
+
+<%= render @like %>
+
+
+ <%= link_to "Edit this like", edit_like_path(@like) %> |
+ <%= link_to "Back to likes", likes_path %>
+
+ <%= button_to "Destroy this like", @like, method: :delete %>
+
diff --git a/app/views/likes/show.json.jbuilder b/app/views/likes/show.json.jbuilder
new file mode 100644
index 000000000..587277f0d
--- /dev/null
+++ b/app/views/likes/show.json.jbuilder
@@ -0,0 +1 @@
+json.partial! "likes/like", like: @like
diff --git a/config/routes.rb b/config/routes.rb
index 9ca7ff2a0..6bed016c5 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,4 +1,5 @@
Rails.application.routes.draw do
+ resources :likes
resources :follow_requests
resources :comments
resources :photos
diff --git a/db/migrate/20240229182950_create_likes.rb b/db/migrate/20240229182950_create_likes.rb
new file mode 100644
index 000000000..e59b96f4d
--- /dev/null
+++ b/db/migrate/20240229182950_create_likes.rb
@@ -0,0 +1,10 @@
+class CreateLikes < ActiveRecord::Migration[7.0]
+ def change
+ create_table :likes do |t|
+ t.references :fan, null: false, foreign_key: { to_table: :users }
+ t.references :photo, null: false, foreign_key: true
+
+ t.timestamps
+ end
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 9d18ec4fd..d89d2b34b 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[7.0].define(version: 2024_02_29_182331) do
+ActiveRecord::Schema[7.0].define(version: 2024_02_29_182950) do
# These are extensions that must be enabled in order to support this database
enable_extension "citext"
enable_extension "plpgsql"
@@ -34,6 +34,15 @@
t.index ["sender_id"], name: "index_follow_requests_on_sender_id"
end
+ create_table "likes", force: :cascade do |t|
+ t.bigint "fan_id", null: false
+ t.bigint "photo_id", null: false
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ t.index ["fan_id"], name: "index_likes_on_fan_id"
+ t.index ["photo_id"], name: "index_likes_on_photo_id"
+ end
+
create_table "photos", force: :cascade do |t|
t.string "image"
t.integer "comments_count", default: 0
@@ -66,5 +75,7 @@
add_foreign_key "comments", "users", column: "author_id"
add_foreign_key "follow_requests", "users", column: "recipient_id"
add_foreign_key "follow_requests", "users", column: "sender_id"
+ add_foreign_key "likes", "photos"
+ add_foreign_key "likes", "users", column: "fan_id"
add_foreign_key "photos", "users", column: "owner_id"
end
From 74b6eb4864b439943974e0118dac8cb50756d0c2 Mon Sep 17 00:00:00 2001
From: Maurius Hill <146677371+mauriushill@users.noreply.github.com>
Date: Thu, 29 Feb 2024 19:55:48 +0000
Subject: [PATCH 09/24] Added photo_count row to Users table.
---
app/models/comment.rb | 2 +-
app/models/like.rb | 2 +-
app/models/photo.rb | 2 +-
app/models/user.rb | 1 +
db/migrate/20240229195220_add_photos_count_to_users.rb | 5 +++++
db/schema.rb | 3 ++-
6 files changed, 11 insertions(+), 4 deletions(-)
create mode 100644 db/migrate/20240229195220_add_photos_count_to_users.rb
diff --git a/app/models/comment.rb b/app/models/comment.rb
index d2fb2066c..519209572 100644
--- a/app/models/comment.rb
+++ b/app/models/comment.rb
@@ -19,6 +19,6 @@
# fk_rails_... (photo_id => photos.id)
#
class Comment < ApplicationRecord
- belongs_to :author, class_name: "User"
+ belongs_to :author, class_name: "User", counter_cache: true
belongs_to :photo
end
diff --git a/app/models/like.rb b/app/models/like.rb
index 53806dcdd..0ac157b3f 100644
--- a/app/models/like.rb
+++ b/app/models/like.rb
@@ -19,6 +19,6 @@
# fk_rails_... (photo_id => photos.id)
#
class Like < ApplicationRecord
- belongs_to :fan, class_name: "User"
+ belongs_to :fan, class_name: "User", counter_cache: true
belongs_to :photo
end
diff --git a/app/models/photo.rb b/app/models/photo.rb
index 83eee0759..c5a5fa371 100644
--- a/app/models/photo.rb
+++ b/app/models/photo.rb
@@ -20,6 +20,6 @@
# fk_rails_... (owner_id => users.id)
#
class Photo < ApplicationRecord
- belongs_to :owner, class_name: "User"
+ belongs_to :owner, class_name: "User", counter_cache: true
has_many :comments
end
diff --git a/app/models/user.rb b/app/models/user.rb
index 4f6f85014..ec4ed9303 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -7,6 +7,7 @@
# email :citext default(""), not null
# encrypted_password :string default(""), not null
# likes_count :integer default(0)
+# photos_count :integer default(0)
# private :boolean
# remember_created_at :datetime
# reset_password_sent_at :datetime
diff --git a/db/migrate/20240229195220_add_photos_count_to_users.rb b/db/migrate/20240229195220_add_photos_count_to_users.rb
new file mode 100644
index 000000000..1ea0117b3
--- /dev/null
+++ b/db/migrate/20240229195220_add_photos_count_to_users.rb
@@ -0,0 +1,5 @@
+class AddPhotosCountToUsers < ActiveRecord::Migration[7.0]
+ def change
+ add_column :users, :photos_count, :integer, default: 0
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index d89d2b34b..571ba65e5 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[7.0].define(version: 2024_02_29_182950) do
+ActiveRecord::Schema[7.0].define(version: 2024_02_29_195220) do
# These are extensions that must be enabled in order to support this database
enable_extension "citext"
enable_extension "plpgsql"
@@ -66,6 +66,7 @@
t.integer "comments_count", default: 0
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
+ t.integer "photos_count", default: 0
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
t.index ["username"], name: "index_users_on_username", unique: true
From 9864e0b1e85e5d3b2a09ed4323d0ffdbad81108b Mon Sep 17 00:00:00 2001
From: Maurius Hill <146677371+mauriushill@users.noreply.github.com>
Date: Thu, 29 Feb 2024 20:08:13 +0000
Subject: [PATCH 10/24] Added has_many method to comments.
---
app/models/user.rb | 1 +
1 file changed, 1 insertion(+)
diff --git a/app/models/user.rb b/app/models/user.rb
index ec4ed9303..35c5bd34c 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -29,4 +29,5 @@ class User < ApplicationRecord
:recoverable, :rememberable, :validatable
has_many :own_photos, class_name: "Photo", foreign_key: "owner_id"
+ has_many :comments, foreign_key: :author_id
end
From 2b9deaa878c6f4a92f2eda6ec02ba383fddc025c Mon Sep 17 00:00:00 2001
From: Maurius Hill <146677371+mauriushill@users.noreply.github.com>
Date: Thu, 29 Feb 2024 20:26:58 +0000
Subject: [PATCH 11/24] Added 'has_many' methods to models with 'belong_to'
statements.
---
app/models/photo.rb | 1 +
app/models/user.rb | 4 ++++
2 files changed, 5 insertions(+)
diff --git a/app/models/photo.rb b/app/models/photo.rb
index c5a5fa371..a59e0669d 100644
--- a/app/models/photo.rb
+++ b/app/models/photo.rb
@@ -22,4 +22,5 @@
class Photo < ApplicationRecord
belongs_to :owner, class_name: "User", counter_cache: true
has_many :comments
+ has_many :likes
end
diff --git a/app/models/user.rb b/app/models/user.rb
index 35c5bd34c..7a1c87597 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -30,4 +30,8 @@ class User < ApplicationRecord
has_many :own_photos, class_name: "Photo", foreign_key: "owner_id"
has_many :comments, foreign_key: :author_id
+ has_many :sent_follow_requests, foreign_key: :sender_id, class_name: "FollowRequest"
+ has_many :recieved_follow_requests, foreign_key: :recipient_id, class_name: "FollowRequest"
+ has_many :likes, foreign_key: :fan_id
+ has_many :own_photos, foreign_key: :owner_id, class_name: "Photo"
end
From 74dae38af6d4597332ffd02a0338f88b99113226 Mon Sep 17 00:00:00 2001
From: Maurius Hill <146677371+mauriushill@users.noreply.github.com>
Date: Thu, 29 Feb 2024 20:58:54 +0000
Subject: [PATCH 12/24] Added methods to the user and photos table.
---
app/models/photo.rb | 1 +
app/models/user.rb | 2 ++
2 files changed, 3 insertions(+)
diff --git a/app/models/photo.rb b/app/models/photo.rb
index a59e0669d..fbf932693 100644
--- a/app/models/photo.rb
+++ b/app/models/photo.rb
@@ -23,4 +23,5 @@ class Photo < ApplicationRecord
belongs_to :owner, class_name: "User", counter_cache: true
has_many :comments
has_many :likes
+ has_many :fans, through: :likes
end
diff --git a/app/models/user.rb b/app/models/user.rb
index 7a1c87597..95a4327a3 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -34,4 +34,6 @@ class User < ApplicationRecord
has_many :recieved_follow_requests, foreign_key: :recipient_id, class_name: "FollowRequest"
has_many :likes, foreign_key: :fan_id
has_many :own_photos, foreign_key: :owner_id, class_name: "Photo"
+ has_many :liked_photos, through: :likes, source: :photo
+ has_many :leaders, through: :sent_follow_requests, source: :recipient
end
From ddadb5667dacdc1c4d8faa1318cc911f92e62f0f Mon Sep 17 00:00:00 2001
From: Maurius Hill <146677371+mauriushill@users.noreply.github.com>
Date: Thu, 29 Feb 2024 21:20:06 +0000
Subject: [PATCH 13/24] Added more associate methods for User table.
---
app/models/user.rb | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/app/models/user.rb b/app/models/user.rb
index 95a4327a3..2e8eb7d5e 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -29,11 +29,28 @@ class User < ApplicationRecord
:recoverable, :rememberable, :validatable
has_many :own_photos, class_name: "Photo", foreign_key: "owner_id"
+
has_many :comments, foreign_key: :author_id
+
has_many :sent_follow_requests, foreign_key: :sender_id, class_name: "FollowRequest"
+
+ has_many :accepted_sent_follow_requests, -> { where(status: "accepted") }, foreign_key: :sender_id, class_name: "FollowRequest"
+
has_many :recieved_follow_requests, foreign_key: :recipient_id, class_name: "FollowRequest"
+
+ has_many :accepted_recieved_follow_requests, -> { where(status: "accepted") }, foreign_key: :recipient_id, class_name: "FollowRequest"
+
has_many :likes, foreign_key: :fan_id
+
has_many :own_photos, foreign_key: :owner_id, class_name: "Photo"
+
has_many :liked_photos, through: :likes, source: :photo
- has_many :leaders, through: :sent_follow_requests, source: :recipient
+
+ has_many :leaders, through: :accepted_sent_follow_requests, source: :recipient
+
+ has_many :followers, through: :accepted_recieved_follow_requests, source: :sender
+
+ has_many :feed, through: :leaders, source: :own_photos
+
+ has_many :discover, through: :leaders, source: :liked_photos
end
From eabd776f9746fd13bda1661c44540407624c7f2f Mon Sep 17 00:00:00 2001
From: Maurius Hill <146677371+mauriushill@users.noreply.github.com>
Date: Thu, 29 Feb 2024 21:59:45 +0000
Subject: [PATCH 14/24] Added validations to tables and added default to
private.
---
app/models/comment.rb | 2 ++
app/models/photo.rb | 3 +++
app/models/user.rb | 2 ++
db/migrate/20240229215718_add_default_to_private.rb | 9 +++++++++
db/schema.rb | 4 ++--
5 files changed, 18 insertions(+), 2 deletions(-)
create mode 100644 db/migrate/20240229215718_add_default_to_private.rb
diff --git a/app/models/comment.rb b/app/models/comment.rb
index 519209572..954390b20 100644
--- a/app/models/comment.rb
+++ b/app/models/comment.rb
@@ -21,4 +21,6 @@
class Comment < ApplicationRecord
belongs_to :author, class_name: "User", counter_cache: true
belongs_to :photo
+
+ validates: :body, presence: true
end
diff --git a/app/models/photo.rb b/app/models/photo.rb
index fbf932693..b1af4727b 100644
--- a/app/models/photo.rb
+++ b/app/models/photo.rb
@@ -24,4 +24,7 @@ class Photo < ApplicationRecord
has_many :comments
has_many :likes
has_many :fans, through: :likes
+
+ validates: :caption, presence: true
+ validates: :image, presence: true
end
diff --git a/app/models/user.rb b/app/models/user.rb
index 2e8eb7d5e..413d64a83 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -53,4 +53,6 @@ class User < ApplicationRecord
has_many :feed, through: :leaders, source: :own_photos
has_many :discover, through: :leaders, source: :liked_photos
+
+ validates :username, presence: true, uniqueness: true
end
diff --git a/db/migrate/20240229215718_add_default_to_private.rb b/db/migrate/20240229215718_add_default_to_private.rb
new file mode 100644
index 000000000..92c85d700
--- /dev/null
+++ b/db/migrate/20240229215718_add_default_to_private.rb
@@ -0,0 +1,9 @@
+class AddDefaultToPrivate < ActiveRecord::Migration[7.0]
+ def change
+ change_column_default(
+ :users,
+ :private,
+ true
+ )
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 571ba65e5..24d952e96 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[7.0].define(version: 2024_02_29_195220) do
+ActiveRecord::Schema[7.0].define(version: 2024_02_29_215718) do
# These are extensions that must be enabled in order to support this database
enable_extension "citext"
enable_extension "plpgsql"
@@ -61,7 +61,7 @@
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.citext "username"
- t.boolean "private"
+ t.boolean "private", default: true
t.integer "likes_count", default: 0
t.integer "comments_count", default: 0
t.datetime "created_at", null: false
From dbf4bbc5b1aed92a1f538be2c6fc6a3ce58e0710 Mon Sep 17 00:00:00 2001
From: Maurius Hill <146677371+mauriushill@users.noreply.github.com>
Date: Thu, 29 Feb 2024 22:11:11 +0000
Subject: [PATCH 15/24] Added scope methods to Photo table.
---
app/models/photo.rb | 3 +++
1 file changed, 3 insertions(+)
diff --git a/app/models/photo.rb b/app/models/photo.rb
index b1af4727b..12c8fa2ee 100644
--- a/app/models/photo.rb
+++ b/app/models/photo.rb
@@ -27,4 +27,7 @@ class Photo < ApplicationRecord
validates: :caption, presence: true
validates: :image, presence: true
+
+ scope :past_week, -> { where(created_at: 1.week.ago...) }
+ scope :by_likes, -> { order(likes_count: :desc) }
end
From aa4523768e861567a31cdd9f45701b028a253183 Mon Sep 17 00:00:00 2001
From: Maurius Hill <146677371+mauriushill@users.noreply.github.com>
Date: Mon, 4 Mar 2024 15:07:19 +0000
Subject: [PATCH 16/24] Added enum method for follow request.
---
app/models/follow_request.rb | 2 ++
app/models/user.rb | 4 ++--
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/app/models/follow_request.rb b/app/models/follow_request.rb
index b2f81264a..1223bf9d6 100644
--- a/app/models/follow_request.rb
+++ b/app/models/follow_request.rb
@@ -22,4 +22,6 @@
class FollowRequest < ApplicationRecord
belongs_to :recipient, class_name: "User"
belongs_to :sender, class_name: "User"
+
+ enum status: { pending: "pending", rejeceted: "rejected", accepted: "accepted" }
end
diff --git a/app/models/user.rb b/app/models/user.rb
index 413d64a83..aafd8cdf1 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -34,11 +34,11 @@ class User < ApplicationRecord
has_many :sent_follow_requests, foreign_key: :sender_id, class_name: "FollowRequest"
- has_many :accepted_sent_follow_requests, -> { where(status: "accepted") }, foreign_key: :sender_id, class_name: "FollowRequest"
+ has_many :accepted_sent_follow_requests, -> { accepted }, foreign_key: :sender_id, class_name: "FollowRequest"
has_many :recieved_follow_requests, foreign_key: :recipient_id, class_name: "FollowRequest"
- has_many :accepted_recieved_follow_requests, -> { where(status: "accepted") }, foreign_key: :recipient_id, class_name: "FollowRequest"
+ has_many :accepted_recieved_follow_requests, -> { accepted }, foreign_key: :recipient_id, class_name: "FollowRequest"
has_many :likes, foreign_key: :fan_id
From 7c48272cded3c3d9e3ea53d6ae5629d50da8a183 Mon Sep 17 00:00:00 2001
From: Maurius Hill <146677371+mauriushill@users.noreply.github.com>
Date: Mon, 4 Mar 2024 15:41:38 +0000
Subject: [PATCH 17/24] Created sample data & updated validations
---
app/models/like.rb | 1 +
app/models/photo.rb | 6 ++++--
lib/tasks/dev.rake | 1 +
3 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/app/models/like.rb b/app/models/like.rb
index 0ac157b3f..cc5cb5c08 100644
--- a/app/models/like.rb
+++ b/app/models/like.rb
@@ -19,6 +19,7 @@
# fk_rails_... (photo_id => photos.id)
#
class Like < ApplicationRecord
+ validates :user_id, uniqueness: { scope: :photo_id, message: "has already liked this photo" }
belongs_to :fan, class_name: "User", counter_cache: true
belongs_to :photo
end
diff --git a/app/models/photo.rb b/app/models/photo.rb
index 12c8fa2ee..ad3a6db90 100644
--- a/app/models/photo.rb
+++ b/app/models/photo.rb
@@ -20,13 +20,15 @@
# fk_rails_... (owner_id => users.id)
#
class Photo < ApplicationRecord
+ validates :caption, presence: true
+ validates :image, presence: true
+
belongs_to :owner, class_name: "User", counter_cache: true
has_many :comments
has_many :likes
has_many :fans, through: :likes
- validates: :caption, presence: true
- validates: :image, presence: true
+
scope :past_week, -> { where(created_at: 1.week.ago...) }
scope :by_likes, -> { order(likes_count: :desc) }
diff --git a/lib/tasks/dev.rake b/lib/tasks/dev.rake
index ca4ae8ef4..a3ecbcf21 100644
--- a/lib/tasks/dev.rake
+++ b/lib/tasks/dev.rake
@@ -1,3 +1,4 @@
desc "Fill the database tables with some sample data"
task({ :sample_data => :environment }) do
+ p "Creating sample data"
end
From 9b249310da6130dac10917940dd8f2ef4ea87451 Mon Sep 17 00:00:00 2001
From: Maurius Hill <146677371+mauriushill@users.noreply.github.com>
Date: Mon, 4 Mar 2024 19:22:20 +0000
Subject: [PATCH 18/24] Added info to dev.rake page for sample data.
---
app/models/comment.rb | 2 +-
app/models/like.rb | 4 +--
lib/tasks/dev.rake | 69 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 72 insertions(+), 3 deletions(-)
diff --git a/app/models/comment.rb b/app/models/comment.rb
index 954390b20..acd1deffd 100644
--- a/app/models/comment.rb
+++ b/app/models/comment.rb
@@ -22,5 +22,5 @@ class Comment < ApplicationRecord
belongs_to :author, class_name: "User", counter_cache: true
belongs_to :photo
- validates: :body, presence: true
+ validates :body, presence: true
end
diff --git a/app/models/like.rb b/app/models/like.rb
index cc5cb5c08..2f3b9484d 100644
--- a/app/models/like.rb
+++ b/app/models/like.rb
@@ -19,7 +19,7 @@
# fk_rails_... (photo_id => photos.id)
#
class Like < ApplicationRecord
- validates :user_id, uniqueness: { scope: :photo_id, message: "has already liked this photo" }
+ validates :fan_id, uniqueness: { scope: :photo_id, message: "has already liked this photo" }
belongs_to :fan, class_name: "User", counter_cache: true
- belongs_to :photo
+ belongs_to :photo, counter_cache: true
end
diff --git a/lib/tasks/dev.rake b/lib/tasks/dev.rake
index a3ecbcf21..fe02127ca 100644
--- a/lib/tasks/dev.rake
+++ b/lib/tasks/dev.rake
@@ -1,4 +1,73 @@
desc "Fill the database tables with some sample data"
task({ :sample_data => :environment }) do
p "Creating sample data"
+
+ if Rails.env.development?
+ FollowRequest.destroy_all
+ Comment.destroy_all
+ Like.destroy_all
+ Photo.destroy_all
+ User.destroy_all
+ end
+
+ 12.times do
+ name = Faker::Name.first_name.downcase
+ u = User.create(
+ email: "#{name}@example.com",
+ username: name,
+ password: "password",
+ private: [true, false].sample
+ )
+
+ p u.errors.full_messages
+ end
+ p "#{User.count} users have been created."
+
+ users = User.all
+
+ users.each do |first_user|
+ users.each do |second_user|
+ if rand < 0.75
+ first_user.sent_follow_requests.create(
+ recipient: second_user,
+ status: FollowRequest.statuses.keys.sample
+ )
+ end
+
+ if rand < 0.75
+ second_user.sent_follow_requests.create(
+ recipient: first_user,
+ status: FollowRequest.statuses.keys.sample
+ )
+ end
+ end
+ end
+ p "There are now #{FollowRequest.count} follow requests."
+
+ users.each do |user|
+ rand(15).times do
+ photo = user.own_photos.create(
+ caption: Faker::Quote.jack_handey,
+ image: "https://robohash.org/#{rand(9999)}"
+ )
+
+ user.followers.each do |follower|
+ if rand < 0.5 && !photo.fans.include?(follower)
+ photo.fans << follower
+ end
+
+ if rand < 0.25
+ photo.comments.create(
+ body: Faker::Quote.jack_handey,
+ author: follower
+ )
+ end
+ end
+ end
+ end
+ p "There are now #{User.count} users."
+ p "There are now #{FollowRequest.count} follow requests."
+ p "There are now #{Photo.count} photos."
+ p "There are now #{Like.count} likes."
+ p "There are now #{Comment.count} comments."
end
From 2e15d2508a130e9b6151c72063c243f9f0389687 Mon Sep 17 00:00:00 2001
From: Maurius Hill <146677371+mauriushill@users.noreply.github.com>
Date: Mon, 4 Mar 2024 21:20:48 +0000
Subject: [PATCH 19/24] Added navbar and CDN assets.
---
app/views/layouts/application.html.erb | 7 ++++++
app/views/shared/_cdn_assets.html.erb | 8 +++++++
app/views/shared/_navbar.html.erb | 31 ++++++++++++++++++++++++++
config/routes.rb | 10 ++++-----
4 files changed, 51 insertions(+), 5 deletions(-)
create mode 100644 app/views/shared/_cdn_assets.html.erb
create mode 100644 app/views/shared/_navbar.html.erb
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb
index 9a595c93a..3918b8c45 100644
--- a/app/views/layouts/application.html.erb
+++ b/app/views/layouts/application.html.erb
@@ -6,11 +6,18 @@
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
+ <%= render partial: "shared/cdn_assets" %>
+
<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
<%= javascript_importmap_tags %>
+
+ <%= render partial: "shared/navbar" %>
+
<%= yield %>
+
+
+ <%= link_to "Show this comment", comment %> +
+ <% end %> +