27 changed files with 633 additions and 34 deletions
@ -0,0 +1,11 @@ |
|||
module FlashesHelper |
|||
FLASH_CLASSES = { alert: "danger", notice: "success", warning: "warning"}.freeze |
|||
|
|||
def flash_class(key) |
|||
FLASH_CLASSES.fetch key.to_sym, key |
|||
end |
|||
|
|||
def user_facing_flashes |
|||
flash.to_hash.slice "alert", "notice", "warning" |
|||
end |
|||
end |
|||
@ -1,3 +1,7 @@ |
|||
// Configure your import map in config/importmap.rb. Read more: https://github.com/rails/importmap-rails
|
|||
import "@hotwired/turbo-rails" |
|||
import "controllers" |
|||
|
|||
//= require popper
|
|||
//= require bootstrap
|
|||
|
|||
|
|||
|
|||
|
|||
@ -1,4 +1,5 @@ |
|||
class Article < ApplicationRecord |
|||
validates :title, presence: true |
|||
validates :body, presence: true, length: { minimum: 10 } |
|||
has_many :votes, class_name: "Vote", foreign_key: "article_id" |
|||
end |
|||
|
|||
@ -1,2 +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 |
|||
|
|||
@ -0,0 +1,3 @@ |
|||
class Vote < ApplicationRecord |
|||
belongs_to :article, class_name: "Article", foreign_key: "article_id" |
|||
end |
|||
@ -1,21 +1,23 @@ |
|||
<%= form_with model: article do |form| %> |
|||
<div> |
|||
<%= form.label :title %><br> |
|||
<%= form.text_field :title %> |
|||
<div class="form-group"> |
|||
<div class="form-group string optional"> |
|||
<%= form.label "标题", :class => "string optional control-label" %> |
|||
<%= form.text_field :title , :class => "string optional form-control" %> |
|||
<% article.errors.full_messages_for(:title).each do |message| %> |
|||
<div><%= message %></div> |
|||
<% end %> |
|||
</div> |
|||
|
|||
<div> |
|||
<%= form.label :body %><br> |
|||
<%= form.text_area :body %><br> |
|||
<div class="form-group string optional"> |
|||
<%= form.label :body , :class => "string optional control-label" %> |
|||
<%= form.text_area :body , :class => "string optional form-control" %> |
|||
<% article.errors.full_messages_for(:body).each do |message| %> |
|||
<div><%= message %></div> |
|||
<% end %> |
|||
</div> |
|||
|
|||
<div> |
|||
<%= form.submit %> |
|||
</div> |
|||
|
|||
<%= form.submit "提交", :class => "btn btn-primary", data: { disable_with: "Submiting..." } %> |
|||
|
|||
<% end %> |
|||
|
|||
@ -1,3 +1,3 @@ |
|||
<h1>Edit Article</h1> |
|||
<h1>修改文章</h1> |
|||
|
|||
<%= render "form", article: @article %> |
|||
@ -0,0 +1,8 @@ |
|||
<% if flash.any? %> |
|||
<% user_facing_flashes.each do |key, value| %> |
|||
<div class="alert alert-<%= flash_class(key) %> alert-dismissable fade show" role="alert"> |
|||
<strong><%= value %> </strong> |
|||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button> |
|||
</div> |
|||
<% end %> |
|||
<% end %> |
|||
@ -0,0 +1,6 @@ |
|||
<footer class="container" style="margin-top: 100px;"> |
|||
<p class="text-center">Copyright ©2017 Rails101 |
|||
<br>Design by |
|||
<a href="http://courses.growthschool.com/courses/rails-101/" target=_new>xdite</a> |
|||
</p> |
|||
</footer> |
|||
@ -0,0 +1,52 @@ |
|||
<nav class="navbar navbar-expand-lg navbar-light bg-light"> |
|||
<div class="container-fluid"> |
|||
<a class="navbar-brand" href="/">WebStack</a> |
|||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> |
|||
<span class="navbar-toggler-icon"></span> |
|||
</button> |
|||
<div class="collapse navbar-collapse" id="navbarSupportedContent"> |
|||
<ul class="navbar-nav me-auto mb-2 mb-lg-0"> |
|||
<li class="nav-item"> |
|||
<a class="nav-link active" aria-current="page" href="/">主页</a> |
|||
</li> |
|||
|
|||
<li class="nav-item dropdown"> |
|||
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false"> |
|||
栏目 |
|||
</a> |
|||
<ul class="dropdown-menu" aria-labelledby="navbarDropdown"> |
|||
<li><a class="dropdown-item" href="#">栏目1</a></li> |
|||
<li><a class="dropdown-item" href="#">栏目2</a></li> |
|||
<li><hr class="dropdown-divider"></li> |
|||
<li><a class="dropdown-item" href="#">栏目3</a></li> |
|||
</ul> |
|||
</li> |
|||
|
|||
<li class="nav-item"> |
|||
<%= link_to("栏目", '/login', class:"nav-link") %> |
|||
</li> |
|||
|
|||
</ul> |
|||
|
|||
|
|||
<% if !current_user %> |
|||
<span class="navbar-text p-1"> |
|||
<%= link_to("注册", new_user_registration_path) %> |
|||
</span> |
|||
<span class="navbar-text"> |
|||
<%= link_to("登录", new_user_session_path) %> |
|||
</span> |
|||
<% else %> |
|||
<span class="navbar-text"> |
|||
<a href="#" class="dropdown-toggle" data-toggle="dropdown"> |
|||
Hi!, <%= current_user.email %> |
|||
<b class="caret"></b> |
|||
</a> |
|||
</span> |
|||
<span class="navbar-text p-1"> |
|||
<%= link_to("退出", destroy_user_session_path, method: :delete) %> |
|||
</span> |
|||
<% end %> |
|||
</div> |
|||
</div> |
|||
</nav> |
|||
@ -0,0 +1,311 @@ |
|||
# 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 = '39aa0d05f06b8f10913aaaff124b5ca77afb859edad5e3f6183e34d2769d26ea37357c55ab66a03b7232a5206f4266463af3ffaf82bd36923d35d1182c636eff' |
|||
|
|||
# ==> 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 = 'd1602f4c09bc7f2fa63ffad1b2b7e3ba266634b3c76b7c130db32bd9ba9ff19bc69534c7345e008edd55ae01024cf1911cacafc7432119f09b815dabc5122215' |
|||
|
|||
# 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] |
|||
|
|||
# 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' |
|||
|
|||
# ==> Turbolinks configuration |
|||
# If your app is using Turbolinks, Turbolinks::Controller needs to be included to make redirection work correctly: |
|||
# |
|||
# ActiveSupport.on_load(:devise_failure_app) do |
|||
# include Turbolinks::Controller |
|||
# end |
|||
|
|||
# ==> 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 |
|||
@ -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:" |
|||
@ -1,12 +1,17 @@ |
|||
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 ("/") |
|||
#root "articles#index" |
|||
#root "welcome#index" |
|||
root "articles#index" |
|||
root "welcome#index" |
|||
#root "articles#index" |
|||
|
|||
resources :articles |
|||
resources :articles do |
|||
member do |
|||
post 'upvote' |
|||
end |
|||
end |
|||
|
|||
end |
|||
|
|||
@ -0,0 +1,9 @@ |
|||
class CreateVotes < ActiveRecord::Migration[7.0] |
|||
def change |
|||
create_table :votes do |t| |
|||
t.integer :article_id |
|||
|
|||
t.timestamps |
|||
end |
|||
end |
|||
end |
|||
@ -0,0 +1,51 @@ |
|||
# frozen_string_literal: true |
|||
|
|||
class AddDeviseToUsers < ActiveRecord::Migration[7.0] |
|||
def self.up |
|||
change_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 |
|||
|
|||
|
|||
# Uncomment below if timestamps were not included in your original model. |
|||
# 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 |
|||
|
|||
def self.down |
|||
# By default, we don't want to make any assumption about how to roll back a migration when your |
|||
# model already existed. Please edit below which fields you would like to remove in this migration. |
|||
raise ActiveRecord::IrreversibleMigration |
|||
end |
|||
end |
|||
@ -0,0 +1,7 @@ |
|||
# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html |
|||
|
|||
one: |
|||
article_id: 1 |
|||
|
|||
two: |
|||
article_id: 1 |
|||
@ -0,0 +1,7 @@ |
|||
require "test_helper" |
|||
|
|||
class VoteTest < ActiveSupport::TestCase |
|||
# test "the truth" do |
|||
# assert true |
|||
# end |
|||
end |
|||
Loading…
Reference in new issue