├── log └── .keep ├── storage └── .keep ├── tmp ├── .keep └── pids │ └── .keep ├── vendor └── .keep ├── lib ├── assets │ └── .keep └── tasks │ └── .keep ├── public ├── favicon.ico ├── apple-touch-icon.png ├── apple-touch-icon-precomposed.png ├── robots.txt ├── 500.html ├── 422.html └── 404.html ├── test ├── helpers │ └── .keep ├── models │ ├── .keep │ ├── user_test.rb │ ├── ticket_test.rb │ └── event_test.rb ├── system │ ├── .keep │ ├── welcomes_test.rb │ └── events_test.rb ├── controllers │ ├── .keep │ ├── sessions_controller_test.rb │ ├── tickets_controller_test.rb │ ├── retirements_controller_test.rb │ ├── welcome_controller_test.rb │ ├── status_controller_test.rb │ └── events_controller_test.rb ├── integration │ └── .keep ├── application_system_test_case.rb ├── factories │ ├── users.rb │ └── events.rb ├── test_helper.rb └── sign_in_helper.rb ├── .ruby-version ├── app ├── assets │ ├── images │ │ └── .keep │ ├── config │ │ └── manifest.js │ └── stylesheets │ │ ├── events.scss │ │ ├── sessions.scss │ │ ├── tickets.scss │ │ ├── welcome.scss │ │ ├── retirements.scss │ │ └── application.css ├── models │ ├── concerns │ │ └── .keep │ ├── application_record.rb │ ├── ticket.rb │ ├── user.rb │ └── event.rb ├── controllers │ ├── concerns │ │ └── .keep │ ├── status_controller.rb │ ├── retirements_controller.rb │ ├── sessions_controller.rb │ ├── welcome_controller.rb │ ├── application_controller.rb │ ├── tickets_controller.rb │ └── events_controller.rb ├── views │ ├── status │ │ └── index.json.jbuilder │ ├── events │ │ ├── create.js.erb │ │ ├── update.js.erb │ │ ├── new.html.haml │ │ ├── edit.html.haml │ │ └── show.html.haml │ ├── kaminari │ │ ├── _gap.html.haml │ │ ├── _last_page.html.haml │ │ ├── _first_page.html.haml │ │ ├── _next_page.html.haml │ │ ├── _prev_page.html.haml │ │ ├── _page.html.haml │ │ └── _paginator.html.haml │ ├── retirements │ │ ├── create.js.erb │ │ └── new.html.haml │ ├── tickets │ │ └── create.js.erb │ ├── application │ │ └── _errors.html.haml │ ├── welcome │ │ └── index.html.haml │ └── layouts │ │ └── application.html.haml ├── helpers │ ├── events_helper.rb │ ├── tickets_helper.rb │ ├── welcome_helper.rb │ ├── sessions_helper.rb │ ├── retirements_helper.rb │ └── application_helper.rb ├── jobs │ └── application_job.rb ├── javascript │ ├── get_form_turbolinks.js │ └── packs │ │ └── application.js └── forms │ └── event_search_form.rb ├── .browserslistrc ├── config ├── webpack │ ├── environment.js │ ├── test.js │ ├── production.js │ └── development.js ├── spring.rb ├── environment.rb ├── initializers │ ├── mime_types.rb │ ├── filter_parameter_logging.rb │ ├── rack_profiler.rb │ ├── application_controller_renderer.rb │ ├── cookies_serializer.rb │ ├── omniauth.rb │ ├── backtrace_silencers.rb │ ├── wrap_parameters.rb │ ├── assets.rb │ ├── inflections.rb │ └── content_security_policy.rb ├── locales │ ├── kaminari_ja.yml │ ├── ja.yml │ └── en.yml ├── boot.rb ├── routes.rb ├── credentials.yml.enc ├── database.yml ├── application.rb ├── storage.yml ├── puma.rb ├── environments │ ├── test.rb │ ├── development.rb │ └── production.rb └── webpacker.yml ├── config.ru ├── .rubocop.yml ├── Rakefile ├── bin ├── rake ├── rails ├── yarn ├── webpack ├── webpack-dev-server ├── spring ├── setup └── bundle ├── postcss.config.js ├── db ├── seeds.rb ├── migrate │ ├── 20200707073202_create_tickets.rb │ ├── 20200707061657_create_users.rb │ ├── 20200707064259_create_events.rb │ └── 20200707093324_create_active_storage_tables.active_storage.rb └── schema.rb ├── package.json ├── .gitignore ├── README.md ├── .github └── workflows │ └── ruby.yml ├── babel.config.js ├── Gemfile └── Gemfile.lock /log/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /storage/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tmp/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vendor/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /lib/assets/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /lib/tasks/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/helpers/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/models/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/system/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tmp/pids/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | 2.6.6 2 | -------------------------------------------------------------------------------- /app/assets/images/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/controllers/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/integration/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.browserslistrc: -------------------------------------------------------------------------------- 1 | defaults 2 | -------------------------------------------------------------------------------- /app/models/concerns/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/apple-touch-icon.png: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/controllers/concerns/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/apple-touch-icon-precomposed.png: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/views/status/index.json.jbuilder: -------------------------------------------------------------------------------- 1 | json.status "ok" -------------------------------------------------------------------------------- /app/helpers/events_helper.rb: -------------------------------------------------------------------------------- 1 | module EventsHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/helpers/tickets_helper.rb: -------------------------------------------------------------------------------- 1 | module TicketsHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/helpers/welcome_helper.rb: -------------------------------------------------------------------------------- 1 | module WelcomeHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/helpers/sessions_helper.rb: -------------------------------------------------------------------------------- 1 | module SessionsHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/helpers/retirements_helper.rb: -------------------------------------------------------------------------------- 1 | module RetirementsHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/assets/config/manifest.js: -------------------------------------------------------------------------------- 1 | //= link_tree ../images 2 | //= link_directory ../stylesheets .css 3 | -------------------------------------------------------------------------------- /app/models/application_record.rb: -------------------------------------------------------------------------------- 1 | class ApplicationRecord < ActiveRecord::Base 2 | self.abstract_class = true 3 | end 4 | -------------------------------------------------------------------------------- /config/webpack/environment.js: -------------------------------------------------------------------------------- 1 | const { environment } = require('@rails/webpacker') 2 | 3 | module.exports = environment 4 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # See https://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file 2 | -------------------------------------------------------------------------------- /app/views/events/create.js.erb: -------------------------------------------------------------------------------- 1 | document.getElementById("errors").innerHTML = "<%= j render("errors", errors: @event.errors) %>" -------------------------------------------------------------------------------- /app/views/events/update.js.erb: -------------------------------------------------------------------------------- 1 | document.getElementById("errors").innerHTML = "<%= j render("errors", errors: @event.errors) %>" -------------------------------------------------------------------------------- /app/views/kaminari/_gap.html.haml: -------------------------------------------------------------------------------- 1 | %li.page-item.disabled 2 | = link_to raw(t 'views.pagination.truncate'), '#', class: 'page-link' 3 | -------------------------------------------------------------------------------- /app/views/retirements/create.js.erb: -------------------------------------------------------------------------------- 1 | document.getElementById("errors").innerHTML = "<%= j render("errors", errors: @current_user.errors) %>" -------------------------------------------------------------------------------- /config/spring.rb: -------------------------------------------------------------------------------- 1 | Spring.watch( 2 | ".ruby-version", 3 | ".rbenv-vars", 4 | "tmp/restart.txt", 5 | "tmp/caching-dev.txt" 6 | ) 7 | -------------------------------------------------------------------------------- /app/views/tickets/create.js.erb: -------------------------------------------------------------------------------- 1 | document.getElementById("createTicketErrors").innerHTML = "<%= j render("errors", errors: @ticket.errors) %>" -------------------------------------------------------------------------------- /app/views/application/_errors.html.haml: -------------------------------------------------------------------------------- 1 | .alert.alert-danger 2 | %ul.mb-0 3 | - errors.full_messages.each do |message| 4 | %li= message -------------------------------------------------------------------------------- /app/helpers/application_helper.rb: -------------------------------------------------------------------------------- 1 | module ApplicationHelper 2 | def url_for_github(user) 3 | "https://github.com/#{user.name}" 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/controllers/status_controller.rb: -------------------------------------------------------------------------------- 1 | class StatusController < ApplicationController 2 | skip_before_action :authenticate 3 | def index 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /config.ru: -------------------------------------------------------------------------------- 1 | # This file is used by Rack-based servers to start the application. 2 | 3 | require_relative 'config/environment' 4 | 5 | run Rails.application 6 | -------------------------------------------------------------------------------- /app/views/kaminari/_last_page.html.haml: -------------------------------------------------------------------------------- 1 | %li.page-item 2 | = link_to_unless current_page.last?, raw(t 'views.pagination.last'), url, remote: remote, class: 'page-link' 3 | -------------------------------------------------------------------------------- /config/environment.rb: -------------------------------------------------------------------------------- 1 | # Load the Rails application. 2 | require_relative 'application' 3 | 4 | # Initialize the Rails application. 5 | Rails.application.initialize! 6 | -------------------------------------------------------------------------------- /test/models/user_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class UserTest < ActiveSupport::TestCase 4 | # test "the truth" do 5 | # assert true 6 | # end 7 | end 8 | -------------------------------------------------------------------------------- /app/views/kaminari/_first_page.html.haml: -------------------------------------------------------------------------------- 1 | %li.page-item 2 | = link_to_unless current_page.first?, raw(t 'views.pagination.first'), url, remote: remote, class: 'page-link' 3 | -------------------------------------------------------------------------------- /test/models/ticket_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class TicketTest < ActiveSupport::TestCase 4 | # test "the truth" do 5 | # assert true 6 | # end 7 | end 8 | -------------------------------------------------------------------------------- /app/views/kaminari/_next_page.html.haml: -------------------------------------------------------------------------------- 1 | %li.page-item 2 | = link_to_unless current_page.last?, raw(t 'views.pagination.next'), url, rel: 'next', remote: remote, class: 'page-link' 3 | -------------------------------------------------------------------------------- /app/views/kaminari/_prev_page.html.haml: -------------------------------------------------------------------------------- 1 | %li.page-item 2 | = link_to_unless current_page.first?, raw(t 'views.pagination.previous'), url, rel: 'prev', remote: remote, class: 'page-link' 3 | -------------------------------------------------------------------------------- /config/webpack/test.js: -------------------------------------------------------------------------------- 1 | process.env.NODE_ENV = process.env.NODE_ENV || 'development' 2 | 3 | const environment = require('./environment') 4 | 5 | module.exports = environment.toWebpackConfig() 6 | -------------------------------------------------------------------------------- /app/models/ticket.rb: -------------------------------------------------------------------------------- 1 | class Ticket < ApplicationRecord 2 | belongs_to :user, optional: true 3 | belongs_to :event 4 | 5 | validates :comment, length: { maximum: 30 }, allow_blank: true 6 | end 7 | -------------------------------------------------------------------------------- /config/webpack/production.js: -------------------------------------------------------------------------------- 1 | process.env.NODE_ENV = process.env.NODE_ENV || 'production' 2 | 3 | const environment = require('./environment') 4 | 5 | module.exports = environment.toWebpackConfig() 6 | -------------------------------------------------------------------------------- /config/initializers/mime_types.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new mime types for use in respond_to blocks: 4 | # Mime::Type.register "text/richtext", :rtf 5 | -------------------------------------------------------------------------------- /config/webpack/development.js: -------------------------------------------------------------------------------- 1 | process.env.NODE_ENV = process.env.NODE_ENV || 'development' 2 | 3 | const environment = require('./environment') 4 | 5 | module.exports = environment.toWebpackConfig() 6 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | require: 2 | - rubocop-performance 3 | - rubocop-rails 4 | 5 | AllCops: 6 | DisabledByDefault: true 7 | 8 | Lint: 9 | Enabled: true 10 | 11 | Security: 12 | Enabled: true 13 | -------------------------------------------------------------------------------- /test/controllers/sessions_controller_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class SessionsControllerTest < ActionDispatch::IntegrationTest 4 | # test "the truth" do 5 | # assert true 6 | # end 7 | end 8 | -------------------------------------------------------------------------------- /test/controllers/tickets_controller_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class TicketsControllerTest < ActionDispatch::IntegrationTest 4 | # test "the truth" do 5 | # assert true 6 | # end 7 | end 8 | -------------------------------------------------------------------------------- /config/locales/kaminari_ja.yml: -------------------------------------------------------------------------------- 1 | ja: 2 | views: 3 | pagination: 4 | first: "« 最初" 5 | last: "最後 »" 6 | previous: "‹ 前" 7 | next: "次 ›" 8 | truncate: "…" -------------------------------------------------------------------------------- /test/controllers/retirements_controller_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class RetirementsControllerTest < ActionDispatch::IntegrationTest 4 | # test "the truth" do 5 | # assert true 6 | # end 7 | end 8 | -------------------------------------------------------------------------------- /app/assets/stylesheets/events.scss: -------------------------------------------------------------------------------- 1 | // Place all the styles related to the events controller here. 2 | // They will automatically be included in application.css. 3 | // You can use Sass (SCSS) here: https://sass-lang.com/ 4 | -------------------------------------------------------------------------------- /app/assets/stylesheets/sessions.scss: -------------------------------------------------------------------------------- 1 | // Place all the styles related to the sessions controller here. 2 | // They will automatically be included in application.css. 3 | // You can use Sass (SCSS) here: https://sass-lang.com/ 4 | -------------------------------------------------------------------------------- /app/assets/stylesheets/tickets.scss: -------------------------------------------------------------------------------- 1 | // Place all the styles related to the tickets controller here. 2 | // They will automatically be included in application.css. 3 | // You can use Sass (SCSS) here: https://sass-lang.com/ 4 | -------------------------------------------------------------------------------- /app/assets/stylesheets/welcome.scss: -------------------------------------------------------------------------------- 1 | // Place all the styles related to the welcome controller here. 2 | // They will automatically be included in application.css. 3 | // You can use Sass (SCSS) here: https://sass-lang.com/ 4 | -------------------------------------------------------------------------------- /app/assets/stylesheets/retirements.scss: -------------------------------------------------------------------------------- 1 | // Place all the styles related to the retirements controller here. 2 | // They will automatically be included in application.css. 3 | // You can use Sass (SCSS) here: https://sass-lang.com/ 4 | -------------------------------------------------------------------------------- /config/boot.rb: -------------------------------------------------------------------------------- 1 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) 2 | 3 | require 'bundler/setup' # Set up gems listed in the Gemfile. 4 | require 'bootsnap/setup' # Speed up boot time by caching expensive operations. 5 | -------------------------------------------------------------------------------- /test/application_system_test_case.rb: -------------------------------------------------------------------------------- 1 | require "test_helper" 2 | 3 | class ApplicationSystemTestCase < ActionDispatch::SystemTestCase 4 | driven_by :selenium, using: :headless_chrome, screen_size: [1400, 1400] 5 | include SignInHelper 6 | end 7 | -------------------------------------------------------------------------------- /config/initializers/filter_parameter_logging.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Configure sensitive parameters which will be filtered from the log file. 4 | Rails.application.config.filter_parameters += [:password] 5 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # Add your own tasks in files placed in lib/tasks ending in .rake, 2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 3 | 4 | require_relative 'config/application' 5 | 6 | Rails.application.load_tasks 7 | -------------------------------------------------------------------------------- /config/initializers/rack_profiler.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | if Rails.env.development? 4 | require "rack-mini-profiler" 5 | 6 | # initialization is skipped so trigger it 7 | Rack::MiniProfilerRails.initialize!(Rails.application) 8 | end 9 | -------------------------------------------------------------------------------- /test/controllers/welcome_controller_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class WelcomeControllerTest < ActionDispatch::IntegrationTest 4 | test "should get index" do 5 | get root_url 6 | assert_response :success 7 | end 8 | 9 | end 10 | -------------------------------------------------------------------------------- /bin/rake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | begin 3 | load File.expand_path('../spring', __FILE__) 4 | rescue LoadError => e 5 | raise unless e.message.include?('spring') 6 | end 7 | require_relative '../config/boot' 8 | require 'rake' 9 | Rake.application.run 10 | -------------------------------------------------------------------------------- /app/views/kaminari/_page.html.haml: -------------------------------------------------------------------------------- 1 | - if page.current? 2 | %li.page-item.active 3 | = content_tag :a, page, data: { remote: remote }, rel: page.rel, class: 'page-link' 4 | - else 5 | %li.page-item 6 | = link_to page, url, remote: remote, rel: page.rel, class: 'page-link' 7 | -------------------------------------------------------------------------------- /app/controllers/retirements_controller.rb: -------------------------------------------------------------------------------- 1 | class RetirementsController < ApplicationController 2 | def new 3 | end 4 | 5 | def create 6 | if current_user.destroy 7 | reset_session 8 | redirect_to root_path, notice: "退会完了しました" 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /test/factories/users.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :user, aliases: [:owner] do 3 | provider { "github" } 4 | sequence(:uid) { |i| "uid#{i}" } 5 | sequence(:name) { |i| "name#{i}" } 6 | sequence(:image_url) { |i| "http://example.com/image#{i}.jpg"} 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /config/initializers/application_controller_renderer.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # ActiveSupport::Reloader.to_prepare do 4 | # ApplicationController.renderer.defaults.merge!( 5 | # http_host: 'example.org', 6 | # https: false 7 | # ) 8 | # end 9 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [ 3 | require('postcss-import'), 4 | require('postcss-flexbugs-fixes'), 5 | require('postcss-preset-env')({ 6 | autoprefixer: { 7 | flexbox: 'no-2009' 8 | }, 9 | stage: 3 10 | }) 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /config/initializers/cookies_serializer.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Specify a serializer for the signed and encrypted cookie jars. 4 | # Valid options are :json, :marshal, and :hybrid. 5 | Rails.application.config.action_dispatch.cookies_serializer = :json 6 | -------------------------------------------------------------------------------- /bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | begin 3 | load File.expand_path('../spring', __FILE__) 4 | rescue LoadError => e 5 | raise unless e.message.include?('spring') 6 | end 7 | APP_PATH = File.expand_path('../config/application', __dir__) 8 | require_relative '../config/boot' 9 | require 'rails/commands' 10 | -------------------------------------------------------------------------------- /app/jobs/application_job.rb: -------------------------------------------------------------------------------- 1 | class ApplicationJob < ActiveJob::Base 2 | # Automatically retry jobs that encountered a deadlock 3 | # retry_on ActiveRecord::Deadlocked 4 | 5 | # Most jobs are safe to ignore if the underlying records are no longer available 6 | # discard_on ActiveJob::DeserializationError 7 | end 8 | -------------------------------------------------------------------------------- /config/locales/ja.yml: -------------------------------------------------------------------------------- 1 | ja: 2 | activerecord: 3 | models: 4 | event: イベント 5 | ticket: チケット 6 | attributes: 7 | event: 8 | name: 名前 9 | place: 場所 10 | start_at: 開始時間 11 | end_at: 終了時間 12 | content: 内容 13 | image: 画像 14 | ticket: 15 | comment: コメント -------------------------------------------------------------------------------- /test/factories/events.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :event do 3 | owner 4 | sequence(:name) { |i| "イベント名#{i}" } 5 | sequence(:place) { |i| "イベント開催場所#{i}" } 6 | sequence(:content) { |i| "イベント本文#{i}" } 7 | start_at { rand(1..30).days.from_now } 8 | end_at { start_at + rand(1..30).hours } 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /bin/yarn: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | APP_ROOT = File.expand_path('..', __dir__) 3 | Dir.chdir(APP_ROOT) do 4 | begin 5 | exec "yarnpkg", *ARGV 6 | rescue Errno::ENOENT 7 | $stderr.puts "Yarn executable was not detected in the system." 8 | $stderr.puts "Download Yarn at https://yarnpkg.com/en/docs/install" 9 | exit 1 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /app/views/retirements/new.html.haml: -------------------------------------------------------------------------------- 1 | %h1.mt-3 退会の確認 2 | 3 | #errors 4 | 5 | %p 退会した場合、ユーザに関するデータがすべて削除されます。 6 | %p ただし、以下の場合は退会できません。 7 | 8 | %ul 9 | %li 10 | 公開中の未終了イベントがある場合 11 | %li 12 | 未終了の参加イベントがある場合 13 | %hr 14 | 15 | = link_to "退会する", retirements_path, method: :post, remote: true, class: "btn btn-danger", data: { confirm: "本当に退会しますか?" } -------------------------------------------------------------------------------- /test/controllers/status_controller_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class StatusControllerTest < ActionDispatch::IntegrationTest 4 | test "GET /status" do 5 | get "/status" 6 | assert_response(:success) 7 | assert_equal({ status: "ok" }.to_json, @response.body) 8 | assert_equal("application/json", @response.media_type) 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /config/initializers/omniauth.rb: -------------------------------------------------------------------------------- 1 | Rails.application.config.middleware.use OmniAuth::Builder do 2 | if Rails.env.development? || Rails.env.test? 3 | provider :github, "YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET" 4 | else 5 | provider :github, 6 | Rails.application.credentials.github[:client_id], 7 | Rails.application.credentials.github[:client_secret] 8 | end 9 | end -------------------------------------------------------------------------------- /db/seeds.rb: -------------------------------------------------------------------------------- 1 | # This file should contain all the record creation needed to seed the database with its default values. 2 | # The data can then be loaded with the rails db:seed command (or created alongside the database with db:setup). 3 | # 4 | # Examples: 5 | # 6 | # movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }]) 7 | # Character.create(name: 'Luke', movie: movies.first) 8 | -------------------------------------------------------------------------------- /db/migrate/20200707073202_create_tickets.rb: -------------------------------------------------------------------------------- 1 | class CreateTickets < ActiveRecord::Migration[6.0] 2 | def change 3 | create_table :tickets do |t| 4 | t.references :user 5 | t.references :event, null: false, foreign_key: true, index: false 6 | t.string :comment 7 | t.timestamps 8 | end 9 | 10 | add_index :tickets, %i[event_id user_id], unique: true 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /db/migrate/20200707061657_create_users.rb: -------------------------------------------------------------------------------- 1 | class CreateUsers < ActiveRecord::Migration[6.0] 2 | def change 3 | create_table :users do |t| 4 | t.string :provider, null: false 5 | t.string :uid, null: false 6 | t.string :name, null: false 7 | t.string :image_url, null: false 8 | t.timestamps 9 | end 10 | 11 | add_index :users, %i[provider uid], unique: true 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "awesome_events", 3 | "private": true, 4 | "dependencies": { 5 | "@rails/activestorage": "^6.0.0", 6 | "@rails/ujs": "^6.0.0", 7 | "@rails/webpacker": "4.2.2", 8 | "bootstrap": "4.4.1", 9 | "jquery": "3.5.1", 10 | "popper.js": "1.16.1", 11 | "turbolinks": "^5.2.0" 12 | }, 13 | "version": "0.1.0", 14 | "devDependencies": { 15 | "webpack-dev-server": "^3.11.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/controllers/sessions_controller.rb: -------------------------------------------------------------------------------- 1 | class SessionsController < ApplicationController 2 | skip_before_action :authenticate, only: :create 3 | 4 | def create 5 | user = User.find_or_create_from_auth_hash!(request.env["omniauth.auth"]) 6 | session[:user_id] = user.id 7 | redirect_to root_path, notice: "ログインしました" 8 | end 9 | 10 | def destroy 11 | reset_session 12 | redirect_to root_path, notice: "ログアウトしました" 13 | end 14 | end -------------------------------------------------------------------------------- /app/controllers/welcome_controller.rb: -------------------------------------------------------------------------------- 1 | class WelcomeController < ApplicationController 2 | skip_before_action :authenticate 3 | 4 | def index 5 | @event_search_form = EventSearchForm.new(event_search_form_params) 6 | @events = @event_search_form.search 7 | end 8 | 9 | private 10 | 11 | def event_search_form_params 12 | params.fetch(:event_search_form, {}).permit(:keyword, :start_at).merge(page: params[:page]) 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /config/routes.rb: -------------------------------------------------------------------------------- 1 | Rails.application.routes.draw do 2 | root "welcome#index" 3 | get "/auth/:provider/callback" => "sessions#create" 4 | delete "/logout" => "sessions#destroy" 5 | 6 | resource :retirements, only: %i[new create] 7 | 8 | resources :events, only: %i[new create show edit update destroy] do 9 | resources :tickets, only: %i[new create destroy] 10 | end 11 | get 'status' => 'status#index', defaults: { format: 'json' } 12 | end 13 | -------------------------------------------------------------------------------- /config/initializers/backtrace_silencers.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. 4 | # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } 5 | 6 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. 7 | # Rails.backtrace_cleaner.remove_silencers! 8 | -------------------------------------------------------------------------------- /app/javascript/get_form_turbolinks.js: -------------------------------------------------------------------------------- 1 | import Turbolinks from "turbolinks" 2 | 3 | document.addEventListener("turbolinks:load", function(event) { 4 | const forms = document.querySelectorAll("form[method=get][data-remote=true]") 5 | for (const form of forms) { 6 | form.addEventListener("ajax:beforeSend", function (event) { 7 | const options = event.detail[1] 8 | 9 | Turbolinks.visit(options.url) 10 | event.preventDefault() 11 | }) 12 | } 13 | }) -------------------------------------------------------------------------------- /config/credentials.yml.enc: -------------------------------------------------------------------------------- 1 | U56WukeIPxLkQXVHYhg9k0m5evN9MI4b9bZwXZeqmbh/tVdsqBISHhJ1OMHBLT3R/bIXK6XQFI5u6o+Z9phoLzEIeQJzXrOfqJJjcLu95QCVJ/cdf0eWnJ8aVVLPaOIinPga+9zgrzVyWdSHMTS1gFUeOIhL4g8rgEDgRq7KJ3L/YlR3cQe31o5oYslL6WFx68phYNc1eWXzUYcLr5lfrFzYSeGSUj4/VEXU+oCs2lYNGjZJZFZSjG5FZ/Vy5GpkElrKNDIw1GcYVlNQFctOynX7lEzg11vW4Ezu5A/MH81kiym+FUowSDbgplUOkBZ6C3aeBcmwPoOCpKxb2KFvohlRdzgY3Igu+HyucDcVggPjs7OKZuNtWgKxciSFS+bqVZYswXqjKiu1gHTx7P/nI36a9PInNnktAmFD--Y1/KbSDOvl3kDAt9--juCYgn8212rfZnW6adCL5A== -------------------------------------------------------------------------------- /db/migrate/20200707064259_create_events.rb: -------------------------------------------------------------------------------- 1 | class CreateEvents < ActiveRecord::Migration[6.0] 2 | def change 3 | create_table :events do |t| 4 | t.bigint :owner_id 5 | t.string :name, null: false 6 | t.string :place, null: false 7 | t.datetime :start_at, null: false 8 | t.datetime :end_at, null: false 9 | t.text :content, null: false 10 | t.timestamps 11 | end 12 | 13 | add_index :events, :owner_id 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /bin/webpack: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development" 4 | ENV["NODE_ENV"] ||= "development" 5 | 6 | require "pathname" 7 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 8 | Pathname.new(__FILE__).realpath) 9 | 10 | require "bundler/setup" 11 | 12 | require "webpacker" 13 | require "webpacker/webpack_runner" 14 | 15 | APP_ROOT = File.expand_path("..", __dir__) 16 | Dir.chdir(APP_ROOT) do 17 | Webpacker::WebpackRunner.run(ARGV) 18 | end 19 | -------------------------------------------------------------------------------- /app/views/kaminari/_paginator.html.haml: -------------------------------------------------------------------------------- 1 | = paginator.render do 2 | %nav 3 | %ul.pagination 4 | = first_page_tag unless current_page.first? 5 | = prev_page_tag unless current_page.first? 6 | - each_page do |page| 7 | - if page.left_outer? || page.right_outer? || page.inside_window? 8 | = page_tag page 9 | - elsif !page.was_truncated? 10 | = gap_tag 11 | = next_page_tag unless current_page.last? 12 | = last_page_tag unless current_page.last? 13 | -------------------------------------------------------------------------------- /bin/webpack-dev-server: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development" 4 | ENV["NODE_ENV"] ||= "development" 5 | 6 | require "pathname" 7 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 8 | Pathname.new(__FILE__).realpath) 9 | 10 | require "bundler/setup" 11 | 12 | require "webpacker" 13 | require "webpacker/dev_server_runner" 14 | 15 | APP_ROOT = File.expand_path("..", __dir__) 16 | Dir.chdir(APP_ROOT) do 17 | Webpacker::DevServerRunner.run(ARGV) 18 | end 19 | -------------------------------------------------------------------------------- /app/controllers/application_controller.rb: -------------------------------------------------------------------------------- 1 | class ApplicationController < ActionController::Base 2 | before_action :authenticate 3 | helper_method :logged_in?, :current_user 4 | 5 | private 6 | 7 | def logged_in? 8 | !!current_user 9 | end 10 | 11 | def current_user 12 | return unless session[:user_id] 13 | @current_user ||= User.find(session[:user_id]) 14 | end 15 | 16 | def authenticate 17 | return if logged_in? 18 | redirect_to root_path, alert: "ログインしてください" 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /config/initializers/wrap_parameters.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # This file contains settings for ActionController::ParamsWrapper which 4 | # is enabled by default. 5 | 6 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. 7 | ActiveSupport.on_load(:action_controller) do 8 | wrap_parameters format: [:json] 9 | end 10 | 11 | # To enable root element in JSON for ActiveRecord objects. 12 | # ActiveSupport.on_load(:active_record) do 13 | # self.include_root_in_json = true 14 | # end 15 | -------------------------------------------------------------------------------- /bin/spring: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | # This file loads Spring without using Bundler, in order to be fast. 4 | # It gets overwritten when you run the `spring binstub` command. 5 | 6 | unless defined?(Spring) 7 | require 'rubygems' 8 | require 'bundler' 9 | 10 | lockfile = Bundler::LockfileParser.new(Bundler.default_lockfile.read) 11 | spring = lockfile.specs.detect { |spec| spec.name == 'spring' } 12 | if spring 13 | Gem.use_paths Gem.dir, Bundler.bundle_path.to_s, *Gem.path 14 | gem 'spring', spring.version 15 | require 'spring/binstub' 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /test/test_helper.rb: -------------------------------------------------------------------------------- 1 | ENV['RAILS_ENV'] ||= 'test' 2 | 3 | # SimpleCov 4 | # require 'simplecov' 5 | # SimpleCov.start 'rails' 6 | 7 | require_relative '../config/environment' 8 | require_relative 'sign_in_helper' 9 | require 'rails/test_help' 10 | require 'minitest/mock' 11 | 12 | class ActiveSupport::TestCase 13 | # Run tests in parallel with specified workers 14 | parallelize(workers: :number_of_processors) 15 | 16 | parallelize_setup do |worker| 17 | # For Searchkick 18 | Searchkick.index_suffix = worker 19 | Event.reindex 20 | Searchkick.disable_callbacks 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /app/forms/event_search_form.rb: -------------------------------------------------------------------------------- 1 | class EventSearchForm 2 | include ActiveModel::Model 3 | include ActiveModel::Attributes 4 | 5 | attribute :keyword, :string 6 | attribute :page, :integer 7 | 8 | def search 9 | Event.search( 10 | keyword_for_search, 11 | where: { start_at: { gte: start_at } }, 12 | page: page, 13 | per_page: 10 14 | ) 15 | end 16 | 17 | def start_at 18 | @start_at || Time.current 19 | end 20 | 21 | def start_at=(new_start_at) 22 | @start_at = new_start_at.in_time_zone 23 | end 24 | 25 | private 26 | 27 | def keyword_for_search 28 | keyword.presence || "*" 29 | end 30 | end -------------------------------------------------------------------------------- /config/initializers/assets.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Version of your assets, change this if you want to expire all your assets. 4 | Rails.application.config.assets.version = '1.0' 5 | 6 | # Add additional assets to the asset load path. 7 | # Rails.application.config.assets.paths << Emoji.images_path 8 | # Add Yarn node_modules folder to the asset load path. 9 | Rails.application.config.assets.paths << Rails.root.join('node_modules') 10 | 11 | # Precompile additional assets. 12 | # application.js, application.css, and all non-JS/CSS in the app/assets 13 | # folder are already added. 14 | # Rails.application.config.assets.precompile += %w( admin.js admin.css ) 15 | -------------------------------------------------------------------------------- /app/controllers/tickets_controller.rb: -------------------------------------------------------------------------------- 1 | class TicketsController < ApplicationController 2 | def new 3 | raise ActionController::RoutingError, "ログイン状態で TicketsController#new にアクセス" 4 | end 5 | 6 | def create 7 | event = Event.find(params[:event_id]) 8 | @ticket = current_user.tickets.build do |t| 9 | t.event = event 10 | t.comment = params[:ticket][:comment] 11 | end 12 | if @ticket.save 13 | redirect_to event, notice: "このイベントに参加表明しました" 14 | end 15 | end 16 | 17 | def destroy 18 | ticket = current_user.tickets.find_by!(event_id: params[:event_id]) 19 | ticket.destroy! 20 | redirect_to event_path(params[:event_id]), notice: "このイベントの参加をキャンセルしました" 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /test/sign_in_helper.rb: -------------------------------------------------------------------------------- 1 | module SignInHelper 2 | def sign_in_as(user) 3 | OmniAuth.config.test_mode = true 4 | OmniAuth.config.add_mock( 5 | user.provider, 6 | uid: user.uid, 7 | info: { nickname: user.name, 8 | image: user.image_url }) 9 | 10 | case 11 | when respond_to?(:visit) 12 | visit root_url 13 | click_on "GitHubでログイン" 14 | when respond_to?(:get) 15 | get "/auth/github/callback" 16 | else 17 | raise NotImplementedError.new 18 | end 19 | @current_user = user 20 | end 21 | 22 | def current_user 23 | @current_user 24 | end 25 | end 26 | 27 | class ActionDispatch::IntegrationTest #((2)) 28 | include SignInHelper #((3)) 29 | end -------------------------------------------------------------------------------- /app/views/welcome/index.html.haml: -------------------------------------------------------------------------------- 1 | %h1 イベント一覧 2 | 3 | = form_with(model: @event_search_form, url: root_path, method: :get) do |f| 4 | .form-group 5 | = f.label :keyword, "キーワード" 6 | = f.text_field :keyword, class: "form-control" 7 | .form-group 8 | = f.label :start_at, "以降に開催されるイベント" 9 | = f.datetime_field :start_at, class: "form-control" 10 | .form-group 11 | = f.submit "検索", class: "btn btn-primary" 12 | 13 | %ul.list-group.mb-3 14 | - @events.each do |event| 15 | = link_to(event, class: "list-group-item list-group-item-action") do 16 | %h5.list-group-item-heading= event.name 17 | %p.mb-1= "#{l(event.start_at, format: :long)} - #{l(event.end_at, format: :long)}" 18 | 19 | = paginate @events 20 | -------------------------------------------------------------------------------- /config/initializers/inflections.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new inflection rules using the following format. Inflections 4 | # are locale specific, and you may define rules for as many different 5 | # locales as you wish. All of these examples are active by default: 6 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 7 | # inflect.plural /^(ox)$/i, '\1en' 8 | # inflect.singular /^(ox)en/i, '\1' 9 | # inflect.irregular 'person', 'people' 10 | # inflect.uncountable %w( fish sheep ) 11 | # end 12 | 13 | # These inflection rules are supported but not enabled by default: 14 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 15 | # inflect.acronym 'RESTful' 16 | # end 17 | -------------------------------------------------------------------------------- /config/database.yml: -------------------------------------------------------------------------------- 1 | # SQLite. Versions 3.8.0 and up are supported. 2 | # gem install sqlite3 3 | # 4 | # Ensure the SQLite 3 gem is defined in your Gemfile 5 | # gem 'sqlite3' 6 | # 7 | default: &default 8 | adapter: sqlite3 9 | pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> 10 | timeout: 5000 11 | 12 | development: 13 | <<: *default 14 | database: db/development.sqlite3 15 | 16 | # Warning: The database defined as "test" will be erased and 17 | # re-generated from your development database when you run "rake". 18 | # Do not set this db to the same as development or production. 19 | test: 20 | <<: *default 21 | database: db/test.sqlite3 22 | 23 | production: 24 | <<: *default 25 | database: db/production.sqlite3 26 | -------------------------------------------------------------------------------- /test/system/welcomes_test.rb: -------------------------------------------------------------------------------- 1 | require "application_system_test_case" 2 | 3 | class WelcomesTest < ApplicationSystemTestCase 4 | test "/ ページを表示" do 5 | visit root_url 6 | 7 | assert_selector "h1", text: "イベント一覧" 8 | end 9 | 10 | test "/ ページを表示して、未来のイベントは表示、過去のイベントは非表示であること" do 11 | Searchkick.enable_callbacks 12 | 13 | future_event = FactoryBot.create(:event, start_at: Time.zone.now + 3.day) 14 | past_event = FactoryBot.create(:event, start_at: Time.zone.now + 1.day) 15 | Event.search_index.refresh 16 | 17 | travel_to Time.zone.now + 2.day do 18 | visit root_url 19 | assert_selector "h5", text: future_event.name 20 | assert_no_selector "h5", text: past_event.name 21 | end 22 | 23 | Searchkick.disable_callbacks 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /app/assets/stylesheets/application.css: -------------------------------------------------------------------------------- 1 | /* 2 | * This is a manifest file that'll be compiled into application.css, which will include all the files 3 | * listed below. 4 | * 5 | * Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's 6 | * vendor/assets/stylesheets directory can be referenced here using a relative path. 7 | * 8 | * You're free to add application-wide styles to this file and they'll appear at the bottom of the 9 | * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS 10 | * files in this directory. Styles in this file should be added after the last require_* statement. 11 | * It is generally better to create a new file per style scope. 12 | * 13 | *= require_tree . 14 | *= require_self 15 | */ 16 | -------------------------------------------------------------------------------- /test/controllers/events_controller_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class EventsControllerTest < ActionDispatch::IntegrationTest 4 | test "自分がつくったイベントは削除できる" do 5 | event_owner = FactoryBot.create(:user) 6 | event = FactoryBot.create(:event, owner: event_owner) 7 | sign_in_as event_owner 8 | assert_difference("Event.count", -1) do 9 | delete event_url(event) 10 | end 11 | end 12 | 13 | test "他の人がつくったイベントは削除できない" do 14 | event_owner = FactoryBot.create(:user) 15 | event = FactoryBot.create(:event, owner: event_owner) 16 | sign_in_user = FactoryBot.create(:user) 17 | sign_in_as sign_in_user 18 | assert_difference("Event.count", 0) do 19 | assert_raises(ActiveRecord::RecordNotFound) do 20 | delete event_url(event) 21 | end 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /app/views/events/new.html.haml: -------------------------------------------------------------------------------- 1 | - now = Time.zone.now 2 | 3 | %h1.mt-2 イベント作成 4 | 5 | = form_with(model: @event, class: "form-horizontal") do |f| 6 | #errors 7 | .form-group 8 | = f.label :name 9 | = f.text_field :name, class: "form-control" 10 | .form-group 11 | = f.label :place 12 | = f.text_field :place, class: "form-control" 13 | .form-group 14 | = f.label :start_at 15 | %div 16 | = f.datetime_select :start_at, start_year: now.year, end_year: now.year + 1 17 | .form-group 18 | = f.label :end_at 19 | %div 20 | = f.datetime_select :end_at, start_year: now.year, end_year: now.year + 1 21 | .form-group 22 | = f.label :content 23 | = f.text_area :content, class: "form-control", row: 10 24 | .form-group 25 | = f.label :image 26 | = f.file_field :image, class: "form-control-file" 27 | = f.submit class: "btn btn-primary" -------------------------------------------------------------------------------- /app/javascript/packs/application.js: -------------------------------------------------------------------------------- 1 | // This file is automatically compiled by Webpack, along with any other files 2 | // present in this directory. You're encouraged to place your actual application logic in 3 | // a relevant structure within app/javascript and only use these pack files to reference 4 | // that code so it'll be compiled. 5 | 6 | require("@rails/ujs").start() 7 | require("turbolinks").start() 8 | require("@rails/activestorage").start() 9 | require("get_form_turbolinks") 10 | 11 | import "bootstrap" 12 | import "bootstrap/scss/bootstrap.scss" 13 | 14 | // Uncomment to copy all static images under ../images to the output folder and reference 15 | // them with the image_pack_tag helper in views (e.g <%= image_pack_tag 'rails.png' %>) 16 | // or the `imagePath` JavaScript helper below. 17 | // 18 | // const images = require.context('../images', true) 19 | // const imagePath = (name) => images(name, true) 20 | -------------------------------------------------------------------------------- /config/application.rb: -------------------------------------------------------------------------------- 1 | require_relative 'boot' 2 | 3 | require "rails" 4 | # Pick the frameworks you want: 5 | require "active_model/railtie" 6 | require "active_job/railtie" 7 | require "active_record/railtie" 8 | require "active_storage/engine" 9 | require "action_controller/railtie" 10 | # require "action_mailer/railtie" 11 | # require "action_mailbox/engine" 12 | # require "action_text/engine" 13 | require "action_view/railtie" 14 | # require "action_cable/engine" 15 | require "sprockets/railtie" 16 | require "rails/test_unit/railtie" 17 | 18 | # Require the gems listed in Gemfile, including any gems 19 | # you've limited to :test, :development, or :production. 20 | Bundler.require(*Rails.groups) 21 | 22 | module AwesomeEvents 23 | class Application < Rails::Application 24 | config.load_defaults 6.0 25 | config.time_zone = "Tokyo" 26 | config.i18n.default_locale = :ja 27 | config.active_storage.variant_processor = :vips 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /config/locales/en.yml: -------------------------------------------------------------------------------- 1 | # Files in the config/locales directory are used for internationalization 2 | # and are automatically loaded by Rails. If you want to use locales other 3 | # than English, add the necessary files in this directory. 4 | # 5 | # To use the locales, use `I18n.t`: 6 | # 7 | # I18n.t 'hello' 8 | # 9 | # In views, this is aliased to just `t`: 10 | # 11 | # <%= t('hello') %> 12 | # 13 | # To use a different locale, set it with `I18n.locale`: 14 | # 15 | # I18n.locale = :es 16 | # 17 | # This would use the information in config/locales/es.yml. 18 | # 19 | # The following keys must be escaped otherwise they will not be retrieved by 20 | # the default I18n backend: 21 | # 22 | # true, false, on, off, yes, no 23 | # 24 | # Instead, surround them with single quotes. 25 | # 26 | # en: 27 | # 'true': 'foo' 28 | # 29 | # To learn more, please read the Rails Internationalization guide 30 | # available at https://guides.rubyonrails.org/i18n.html. 31 | 32 | en: 33 | hello: "Hello world" 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files for more about ignoring files. 2 | # 3 | # If you find yourself ignoring temporary files generated by your text editor 4 | # or operating system, you probably want to add a global ignore instead: 5 | # git config --global core.excludesfile '~/.gitignore_global' 6 | 7 | # Ignore bundler config. 8 | /.bundle 9 | 10 | # Ignore the default SQLite database. 11 | /db/*.sqlite3 12 | /db/*.sqlite3-journal 13 | /db/*.sqlite3-* 14 | 15 | # Ignore all logfiles and tempfiles. 16 | /log/* 17 | /tmp/* 18 | !/log/.keep 19 | !/tmp/.keep 20 | 21 | # Ignore pidfiles, but keep the directory. 22 | /tmp/pids/* 23 | !/tmp/pids/ 24 | !/tmp/pids/.keep 25 | 26 | # Ignore uploaded files in development. 27 | /storage/* 28 | !/storage/.keep 29 | 30 | /public/assets 31 | .byebug_history 32 | 33 | # Ignore master key for decrypting credentials and more. 34 | /config/master.key 35 | 36 | /public/packs 37 | /public/packs-test 38 | /node_modules 39 | /yarn-error.log 40 | yarn-debug.log* 41 | .yarn-integrity 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # awesome events 2 | 3 | これは、パーフェクトRuby on Rails第2版の第6章以降で作成されたサンプルアプリケーションです。 4 | 5 | イベント情報を登録/編集したり、イベントに参加登録したりできます。 6 | 7 | ## 前提条件 8 | 9 | 次のライブラリをインストールしておいてください。詳しくは書籍を参考にしてください。 10 | 11 | * Ruby 2.6.6 12 | * Google Chrome 13 | * Node.js 14 | * Yarn 15 | * libvips 16 | * Elasticsearch 17 | * Japanese (kuromoji) Analysis Plugin 18 | 19 | ## セットアップ方法 20 | 21 | ```sh 22 | https://github.com/perfect-ruby-on-rails/awesome_events.git 23 | cd awesome_events 24 | bundle install 25 | yarn install 26 | bin/rails db:setup 27 | ``` 28 | 29 | 第6章 OAuthを利用して「GitHubでログイン」機能を作る を参考に、GitHubアプリケーションを登録します。手に入れたClient IDとClient Secretを`config/initializers/omniauth.rb`に設定します。 30 | 31 | 次のコマンドでElasticsearchを起動します 32 | 33 | ```sh 34 | elasticsearch 35 | ``` 36 | 37 | 次のコマンドでサーバが立ち上がり、 http://localhost:3000 でアクセスできます。 38 | 39 | ```sh 40 | ./bin/rails s 41 | ``` 42 | 43 | ## テストの実行方法 44 | 45 | ### システムテストの実行方法 46 | 47 | elasticsearchを起動した状態で次のコマンドを実行します。 48 | 49 | ```sh 50 | bin/rails test:system 51 | ``` 52 | 53 | ### システムテスト以外のテストの実行方法 54 | 55 | 次のコマンドを実行します。 56 | 57 | ```sh 58 | bin/rails test 59 | ``` 60 | 61 | -------------------------------------------------------------------------------- /app/models/user.rb: -------------------------------------------------------------------------------- 1 | class User < ApplicationRecord 2 | before_destroy :check_all_events_finished 3 | 4 | has_many :created_events, class_name: "Event", foreign_key: "owner_id", dependent: :nullify 5 | has_many :tickets, dependent: :nullify 6 | has_many :participating_events, through: :tickets, source: :event 7 | 8 | def self.find_or_create_from_auth_hash!(auth_hash) 9 | provider = auth_hash[:provider] 10 | uid = auth_hash[:uid] 11 | nickname = auth_hash[:info][:nickname] 12 | image_url = auth_hash[:info][:image] 13 | 14 | User.find_or_create_by!(provider: provider, uid: uid) do |user| # ((1)) 15 | user.name = nickname 16 | user.image_url = image_url 17 | end 18 | end 19 | 20 | private 21 | 22 | def check_all_events_finished 23 | now = Time.zone.now 24 | if created_events.where(":now < end_at", now: now).exists? 25 | errors[:base] << "公開中の未終了イベントが存在します。" 26 | end 27 | 28 | if participating_events.where(":now < end_at", now: now).exists? 29 | errors[:base] << "未終了の参加イベントが存在します。" 30 | end 31 | 32 | throw(:abort) unless errors.empty? 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /db/migrate/20200707093324_create_active_storage_tables.active_storage.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from active_storage (originally 20170806125915) 2 | class CreateActiveStorageTables < ActiveRecord::Migration[5.2] 3 | def change 4 | create_table :active_storage_blobs do |t| 5 | t.string :key, null: false 6 | t.string :filename, null: false 7 | t.string :content_type 8 | t.text :metadata 9 | t.bigint :byte_size, null: false 10 | t.string :checksum, null: false 11 | t.datetime :created_at, null: false 12 | 13 | t.index [ :key ], unique: true 14 | end 15 | 16 | create_table :active_storage_attachments do |t| 17 | t.string :name, null: false 18 | t.references :record, null: false, polymorphic: true, index: false 19 | t.references :blob, null: false 20 | 21 | t.datetime :created_at, null: false 22 | 23 | t.index [ :record_type, :record_id, :name, :blob_id ], name: "index_active_storage_attachments_uniqueness", unique: true 24 | t.foreign_key :active_storage_blobs, column: :blob_id 25 | end 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'fileutils' 3 | 4 | # path to your application root. 5 | APP_ROOT = File.expand_path('..', __dir__) 6 | 7 | def system!(*args) 8 | system(*args) || abort("\n== Command #{args} failed ==") 9 | end 10 | 11 | FileUtils.chdir APP_ROOT do 12 | # This script is a way to setup or update your development environment automatically. 13 | # This script is idempotent, so that you can run it at anytime and get an expectable outcome. 14 | # Add necessary setup steps to this file. 15 | 16 | puts '== Installing dependencies ==' 17 | system! 'gem install bundler --conservative' 18 | system('bundle check') || system!('bundle install') 19 | 20 | # Install JavaScript dependencies 21 | # system('bin/yarn') 22 | 23 | # puts "\n== Copying sample files ==" 24 | # unless File.exist?('config/database.yml') 25 | # FileUtils.cp 'config/database.yml.sample', 'config/database.yml' 26 | # end 27 | 28 | puts "\n== Preparing database ==" 29 | system! 'bin/rails db:prepare' 30 | 31 | puts "\n== Removing old logs and tempfiles ==" 32 | system! 'bin/rails log:clear tmp:clear' 33 | 34 | puts "\n== Restarting application server ==" 35 | system! 'bin/rails restart' 36 | end 37 | -------------------------------------------------------------------------------- /app/views/events/edit.html.haml: -------------------------------------------------------------------------------- 1 | - now = Time.zone.now 2 | 3 | %h1.mt-2 イベント情報編集 4 | 5 | = form_with(model: @event, class: "form-horizontal") do |f| 6 | #errors 7 | .form-group 8 | = f.label :name 9 | = f.text_field :name, class: "form-control" 10 | .form-group 11 | = f.label :place 12 | = f.text_field :place, class: "form-control" 13 | .form-group 14 | = f.label :start_at 15 | %div 16 | = f.datetime_select :start_at, start_year: now.year, end_year: now.year + 1 17 | .form-group 18 | = f.label :end_at 19 | %div 20 | = f.datetime_select :end_at, start_year: now.year, end_year: now.year + 1 21 | .form-group 22 | = f.label :content 23 | = f.text_area :content, class: "form-control", row: 10 24 | .form-group 25 | = f.label :image 26 | - if @event.image.attached? && @event.image.blob&.persisted? 27 | = image_tag(@event.image.variant(resize_to_fit: [200, 200]), class: "img-thumbnail d-block mb-3") 28 | = f.file_field :image, class: "form-control-file" 29 | - if @event.image.attached? && @event.image.blob&.persisted? 30 | .checkbox 31 | %label 32 | = f.check_box :remove_image 33 | 画像を削除する 34 | = f.submit class: "btn btn-primary" -------------------------------------------------------------------------------- /config/storage.yml: -------------------------------------------------------------------------------- 1 | test: 2 | service: Disk 3 | root: <%= Rails.root.join("tmp/storage") %> 4 | 5 | local: 6 | service: Disk 7 | root: <%= Rails.root.join("storage") %> 8 | 9 | # Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key) 10 | # amazon: 11 | # service: S3 12 | # access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %> 13 | # secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %> 14 | # region: us-east-1 15 | # bucket: your_own_bucket 16 | 17 | # Remember not to checkin your GCS keyfile to a repository 18 | # google: 19 | # service: GCS 20 | # project: your_project 21 | # credentials: <%= Rails.root.join("path/to/gcs.keyfile") %> 22 | # bucket: your_own_bucket 23 | 24 | # Use rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key) 25 | # microsoft: 26 | # service: AzureStorage 27 | # storage_account_name: your_account_name 28 | # storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %> 29 | # container: your_container_name 30 | 31 | # mirror: 32 | # service: Mirror 33 | # primary: local 34 | # mirrors: [ amazon, google, microsoft ] 35 | -------------------------------------------------------------------------------- /.github/workflows/ruby.yml: -------------------------------------------------------------------------------- 1 | name: Rails Tests 2 | on: [push, pull_request] 3 | jobs: 4 | build: 5 | runs-on: ubuntu-latest 6 | steps: 7 | - uses: actions/checkout@v2 8 | - name: Set up Ruby 2.6 9 | uses: ruby/setup-ruby@v1 10 | with: 11 | ruby-version: 2.6 12 | - name: Configure sysctl limits 13 | run: | 14 | sudo swapoff -a 15 | sudo sysctl -w vm.swappiness=1 16 | sudo sysctl -w fs.file-max=262144 17 | sudo sysctl -w vm.max_map_count=262144 18 | - name: Run Elasticsearch 19 | uses: perfect-ruby-on-rails/elasticsearch-with-plugins-action@v1 20 | with: 21 | stack-version: 7.6.0 22 | plugins: | 23 | analysis-kuromoji 24 | - name: Build and test 25 | env: 26 | RAILS_ENV: test 27 | run: | 28 | sudo apt-get -yqq install libsqlite3-dev 29 | bundle install --jobs 4 --retry 3 30 | bin/rails db:create 31 | bin/rails db:migrate 32 | bin/yarn install 33 | bin/rails test 34 | bin/rails test:system 35 | # - name: Upload 36 | # uses: actions/upload-artifact@v2 37 | # if: failure() 38 | # with: 39 | # name: my-uploads 40 | # path: tmp/screenshots/ 41 | -------------------------------------------------------------------------------- /app/controllers/events_controller.rb: -------------------------------------------------------------------------------- 1 | class EventsController < ApplicationController 2 | skip_before_action :authenticate, only: :show 3 | 4 | def show 5 | @event = Event.find(params[:id]) 6 | @ticket = current_user && current_user.tickets.find_by(event: @event) 7 | @tickets = @event.tickets.includes(:user).order(:created_at) 8 | end 9 | 10 | def new 11 | @event = current_user.created_events.build 12 | end 13 | 14 | def create 15 | @event = current_user.created_events.build(event_params) 16 | 17 | if @event.save 18 | redirect_to @event, notice: "作成しました" 19 | end 20 | end 21 | 22 | def edit 23 | @event = current_user.created_events.find(params[:id]) 24 | end 25 | 26 | def update 27 | @event = current_user.created_events.find(params[:id]) 28 | if @event.update(event_params) 29 | redirect_to @event, notice: "更新しました" 30 | end 31 | end 32 | 33 | def destroy 34 | @event = current_user.created_events.find(params[:id]) 35 | @event.destroy! 36 | redirect_to root_path, notice: "削除しました" 37 | end 38 | 39 | private 40 | 41 | def event_params 42 | params.require(:event).permit( 43 | :name, :place, :image, :remove_image, :content, :start_at, :end_at 44 | ) 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /app/views/layouts/application.html.haml: -------------------------------------------------------------------------------- 1 | !!! 2 | %html 3 | %head 4 | %meta{ content: "text/html; charset=UTF-8", "http-equiv": "Content-Type" } 5 | %title AwesomeEvents 6 | = csrf_meta_tags 7 | = csp_meta_tag 8 | = stylesheet_link_tag "application", media: "all", "data-turbolinks-track": "reload" 9 | = javascript_pack_tag "application", "data-turbolinks-track": "reload" 10 | %body 11 | %header.navbar.navbar-expand-sm.navbar-light.bg-light 12 | .container 13 | = link_to "AwesomeEvents", root_path, class: "navbar-brand mr-auto" 14 | %ul.navbar-nav 15 | %li.nav-item 16 | = link_to "イベントを作る", new_event_path, class: "nav-link" 17 | - if logged_in? 18 | %li.nav-item 19 | = link_to "退会", new_retirements_path, class: "nav-link" 20 | %li.nav-item 21 | = link_to "ログアウト", logout_path, class: "nav-link", method: :delete 22 | - else 23 | %li.nav-item 24 | = link_to "GitHubでログイン", "/auth/github", class: "nav-link", method: :post 25 | .container 26 | - if flash.notice 27 | .alert.alert-success 28 | = flash.notice 29 | - if flash.alert 30 | .alert.alert-danger 31 | = flash.alert 32 | = yield -------------------------------------------------------------------------------- /test/models/event_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class EventTest < ActiveSupport::TestCase 4 | test '#created_by? owner_id と 引数の#id が同じとき' do 5 | event = FactoryBot.create(:event) 6 | user = MiniTest::Mock.new.expect(:id, event.owner_id) 7 | assert_equal(true, event.created_by?(user)) 8 | user.verify 9 | end 10 | 11 | test '#created_by? owner_id と 引数の#id が異なるとき' do 12 | event = FactoryBot.create(:event) 13 | another_user = FactoryBot.create(:user) 14 | assert_equal(false, event.created_by?(another_user)) 15 | end 16 | 17 | test '#created_by? 引数が nil なとき' do 18 | event = FactoryBot.create(:event) 19 | assert_equal(false, event.created_by?(nil)) 20 | end 21 | 22 | test 'start_at_should_be_before_end_at validation OK' do 23 | start_at = rand(1..30).days.from_now 24 | end_at = start_at + rand(1..30).hours 25 | event = FactoryBot.build(:event, 26 | start_at: start_at, end_at: end_at) 27 | event.valid? 28 | assert_empty(event.errors[:start_at]) 29 | end 30 | 31 | test 'start_at_should_be_before_end_at validation error' do 32 | start_at = rand(1..30).days.from_now 33 | end_at = start_at - rand(1..30).hours 34 | event = FactoryBot.build(:event, 35 | start_at: start_at, end_at: end_at) 36 | event.valid? 37 | assert_not_empty(event.errors[:start_at]) 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /app/models/event.rb: -------------------------------------------------------------------------------- 1 | class Event < ApplicationRecord 2 | searchkick language: "japanese" 3 | 4 | has_one_attached :image 5 | has_many :tickets, dependent: :destroy 6 | belongs_to :owner, class_name: "User" 7 | 8 | validates :image, 9 | content_type: [:png, :jpg, :jpeg], 10 | size: { less_than_or_equal_to: 10.megabytes }, 11 | dimension: { width: { max: 2000 } , height: { max: 2000 } } 12 | validates :name, length: { maximum: 50 }, presence: true 13 | validates :place, length: { maximum: 100 }, presence: true 14 | validates :content, length: { maximum: 2000 }, presence: true 15 | validates :start_at, presence: true 16 | validates :end_at, presence: true 17 | validate :start_at_should_be_before_end_at 18 | 19 | attr_accessor :remove_image 20 | 21 | before_save :remove_image_if_user_accept 22 | 23 | def created_by?(user) 24 | return false unless user 25 | owner_id == user.id 26 | end 27 | 28 | private 29 | 30 | def remove_image_if_user_accept 31 | self.image = nil if ActiveRecord::Type::Boolean.new.cast(remove_image) 32 | end 33 | 34 | def start_at_should_be_before_end_at 35 | return unless start_at && end_at 36 | 37 | if start_at >= end_at 38 | errors.add(:start_at, "は終了時間よりも前に設定してください") 39 | end 40 | end 41 | 42 | def search_data 43 | { 44 | name: name, 45 | place: place, 46 | content: content, 47 | owner_name: owner&.name, 48 | start_at: start_at 49 | } 50 | end 51 | end 52 | -------------------------------------------------------------------------------- /config/initializers/content_security_policy.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Define an application-wide content security policy 4 | # For further information see the following documentation 5 | # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy 6 | 7 | # Rails.application.config.content_security_policy do |policy| 8 | # policy.default_src :self, :https 9 | # policy.font_src :self, :https, :data 10 | # policy.img_src :self, :https, :data 11 | # policy.object_src :none 12 | # policy.script_src :self, :https 13 | # policy.style_src :self, :https 14 | # # If you are using webpack-dev-server then specify webpack-dev-server host 15 | # policy.connect_src :self, :https, "http://localhost:3035", "ws://localhost:3035" if Rails.env.development? 16 | 17 | # # Specify URI for violation reports 18 | # # policy.report_uri "/csp-violation-report-endpoint" 19 | # end 20 | 21 | # If you are using UJS then enable automatic nonce generation 22 | # Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) } 23 | 24 | # Set the nonce only to specific directives 25 | # Rails.application.config.content_security_policy_nonce_directives = %w(script-src) 26 | 27 | # Report CSP violations to a specified URI 28 | # For further information see the following documentation: 29 | # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only 30 | # Rails.application.config.content_security_policy_report_only = true 31 | -------------------------------------------------------------------------------- /config/puma.rb: -------------------------------------------------------------------------------- 1 | # Puma can serve each request in a thread from an internal thread pool. 2 | # The `threads` method setting takes two numbers: a minimum and maximum. 3 | # Any libraries that use thread pools should be configured to match 4 | # the maximum value specified for Puma. Default is set to 5 threads for minimum 5 | # and maximum; this matches the default thread size of Active Record. 6 | # 7 | max_threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 } 8 | min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count } 9 | threads min_threads_count, max_threads_count 10 | 11 | # Specifies the `port` that Puma will listen on to receive requests; default is 3000. 12 | # 13 | port ENV.fetch("PORT") { 3000 } 14 | 15 | # Specifies the `environment` that Puma will run in. 16 | # 17 | environment ENV.fetch("RAILS_ENV") { "development" } 18 | 19 | # Specifies the `pidfile` that Puma will use. 20 | pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" } 21 | 22 | # Specifies the number of `workers` to boot in clustered mode. 23 | # Workers are forked web server processes. If using threads and workers together 24 | # the concurrency of the application would be max `threads` * `workers`. 25 | # Workers do not work on JRuby or Windows (both of which do not support 26 | # processes). 27 | # 28 | # workers ENV.fetch("WEB_CONCURRENCY") { 2 } 29 | 30 | # Use the `preload_app!` method when specifying a `workers` number. 31 | # This directive tells Puma to first boot the application and load code 32 | # before forking the application. This takes advantage of Copy On Write 33 | # process behavior so workers use less memory. 34 | # 35 | # preload_app! 36 | 37 | # Allow puma to be restarted by `rails restart` command. 38 | plugin :tmp_restart 39 | -------------------------------------------------------------------------------- /config/environments/test.rb: -------------------------------------------------------------------------------- 1 | # The test environment is used exclusively to run your application's 2 | # test suite. You never need to work with it otherwise. Remember that 3 | # your test database is "scratch space" for the test suite and is wiped 4 | # and recreated between test runs. Don't rely on the data there! 5 | 6 | Rails.application.configure do 7 | # Settings specified here will take precedence over those in config/application.rb. 8 | 9 | config.cache_classes = false 10 | config.action_view.cache_template_loading = true 11 | 12 | # Do not eager load code on boot. This avoids loading your whole application 13 | # just for the purpose of running a single test. If you are using a tool that 14 | # preloads Rails for running tests, you may have to set it to true. 15 | config.eager_load = false 16 | 17 | # Configure public file server for tests with Cache-Control for performance. 18 | config.public_file_server.enabled = true 19 | config.public_file_server.headers = { 20 | 'Cache-Control' => "public, max-age=#{1.hour.to_i}" 21 | } 22 | 23 | # Show full error reports and disable caching. 24 | config.consider_all_requests_local = true 25 | config.action_controller.perform_caching = false 26 | config.cache_store = :null_store 27 | 28 | # Raise exceptions instead of rendering exception templates. 29 | config.action_dispatch.show_exceptions = false 30 | 31 | # Disable request forgery protection in test environment. 32 | config.action_controller.allow_forgery_protection = false 33 | 34 | # Store uploaded files on the local file system in a temporary directory. 35 | config.active_storage.service = :test 36 | 37 | # Print deprecation notices to the stderr. 38 | config.active_support.deprecation = :stderr 39 | 40 | # Raises error for missing translations. 41 | # config.action_view.raise_on_missing_translations = true 42 | end 43 | -------------------------------------------------------------------------------- /public/500.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | We're sorry, but something went wrong (500) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

We're sorry, but something went wrong.

62 |
63 |

If you are the application owner check the logs for more information.

64 |
65 | 66 | 67 | -------------------------------------------------------------------------------- /test/system/events_test.rb: -------------------------------------------------------------------------------- 1 | require "application_system_test_case" 2 | 3 | class EventsTest < ApplicationSystemTestCase 4 | test "/events/:id ページを表示" do 5 | event = FactoryBot.create(:event) 6 | visit event_url(event) 7 | assert_selector "h1", text: event.name 8 | end 9 | 10 | test "/events/new ページでフォームへ記入して登録" do 11 | sign_in_as(FactoryBot.create(:user)) 12 | 13 | visit new_event_url 14 | assert_selector "h1", text: "イベント作成" 15 | 16 | fill_in "名前", with: "TokyuRubyKaigi" 17 | fill_in "場所", with: "東京" 18 | fill_in "内容", with: "tokyu.rbによる地域Ruby会議" 19 | 20 | start_at = Time.current 21 | end_at = start_at + 3.hour 22 | 23 | start_at_field = "event_start_at" 24 | select start_at.strftime("%Y"), from: "#{start_at_field}_1i" # 年 25 | select I18n.l(start_at, format: '%B'), from: "#{start_at_field}_2i" # 月 26 | select start_at.strftime("%-d"), from: "#{start_at_field}_3i" # 日 27 | select start_at.strftime("%H"), from: "#{start_at_field}_4i" # 時 28 | select start_at.strftime("%M"), from: "#{start_at_field}_5i" # 分 29 | 30 | end_at_field = "event_end_at" 31 | select end_at.strftime("%Y"), from: "#{end_at_field}_1i" # 年 32 | select I18n.l(end_at, format: '%B'), from: "#{end_at_field}_2i" # 月 33 | select end_at.strftime("%-d"), from: "#{end_at_field}_3i" # 日 34 | select end_at.strftime("%H"), from: "#{end_at_field}_4i" # 時 35 | select end_at.strftime("%M"), from: "#{end_at_field}_5i" # 分 36 | 37 | click_on "登録する" 38 | assert_selector "div.alert", text: "作成しました" 39 | end 40 | 41 | test "/events/:id ページを表示して削除ボタンを押す" do 42 | sign_in_as(FactoryBot.create(:user)) 43 | event = FactoryBot.create(:event, owner: current_user) 44 | visit event_url(event) 45 | assert_difference("Event.count", -1) do 46 | accept_confirm do 47 | click_on "イベントを削除する" 48 | end 49 | assert_selector "div.alert", text: "削除しました" 50 | end 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /public/422.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | The change you wanted was rejected (422) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

The change you wanted was rejected.

62 |

Maybe you tried to change something you didn't have access to.

63 |
64 |

If you are the application owner check the logs for more information.

65 |
66 | 67 | 68 | -------------------------------------------------------------------------------- /public/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | The page you were looking for doesn't exist (404) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

The page you were looking for doesn't exist.

62 |

You may have mistyped the address or the page may have moved.

63 |
64 |

If you are the application owner check the logs for more information.

65 |
66 | 67 | 68 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function(api) { 2 | var validEnv = ['development', 'test', 'production'] 3 | var currentEnv = api.env() 4 | var isDevelopmentEnv = api.env('development') 5 | var isProductionEnv = api.env('production') 6 | var isTestEnv = api.env('test') 7 | 8 | if (!validEnv.includes(currentEnv)) { 9 | throw new Error( 10 | 'Please specify a valid `NODE_ENV` or ' + 11 | '`BABEL_ENV` environment variables. Valid values are "development", ' + 12 | '"test", and "production". Instead, received: ' + 13 | JSON.stringify(currentEnv) + 14 | '.' 15 | ) 16 | } 17 | 18 | return { 19 | presets: [ 20 | isTestEnv && [ 21 | '@babel/preset-env', 22 | { 23 | targets: { 24 | node: 'current' 25 | } 26 | } 27 | ], 28 | (isProductionEnv || isDevelopmentEnv) && [ 29 | '@babel/preset-env', 30 | { 31 | forceAllTransforms: true, 32 | useBuiltIns: 'entry', 33 | corejs: 3, 34 | modules: false, 35 | exclude: ['transform-typeof-symbol'] 36 | } 37 | ] 38 | ].filter(Boolean), 39 | plugins: [ 40 | 'babel-plugin-macros', 41 | '@babel/plugin-syntax-dynamic-import', 42 | isTestEnv && 'babel-plugin-dynamic-import-node', 43 | '@babel/plugin-transform-destructuring', 44 | [ 45 | '@babel/plugin-proposal-class-properties', 46 | { 47 | loose: true 48 | } 49 | ], 50 | [ 51 | '@babel/plugin-proposal-object-rest-spread', 52 | { 53 | useBuiltIns: true 54 | } 55 | ], 56 | [ 57 | '@babel/plugin-transform-runtime', 58 | { 59 | helpers: false, 60 | regenerator: true, 61 | corejs: false 62 | } 63 | ], 64 | [ 65 | '@babel/plugin-transform-regenerator', 66 | { 67 | async: false 68 | } 69 | ] 70 | ].filter(Boolean) 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /config/environments/development.rb: -------------------------------------------------------------------------------- 1 | Rails.application.configure do 2 | # Settings specified here will take precedence over those in config/application.rb. 3 | 4 | # In the development environment your application's code is reloaded on 5 | # every request. This slows down response time but is perfect for development 6 | # since you don't have to restart the web server when you make code changes. 7 | config.cache_classes = false 8 | 9 | # Do not eager load code on boot. 10 | config.eager_load = false 11 | 12 | # Show full error reports. 13 | config.consider_all_requests_local = true 14 | 15 | # Enable/disable caching. By default caching is disabled. 16 | # Run rails dev:cache to toggle caching. 17 | if Rails.root.join('tmp', 'caching-dev.txt').exist? 18 | config.action_controller.perform_caching = true 19 | config.action_controller.enable_fragment_cache_logging = true 20 | 21 | config.cache_store = :memory_store 22 | config.public_file_server.headers = { 23 | 'Cache-Control' => "public, max-age=#{2.days.to_i}" 24 | } 25 | else 26 | config.action_controller.perform_caching = false 27 | 28 | config.cache_store = :null_store 29 | end 30 | 31 | # Store uploaded files on the local file system (see config/storage.yml for options). 32 | config.active_storage.service = :local 33 | 34 | # Print deprecation notices to the Rails logger. 35 | config.active_support.deprecation = :log 36 | 37 | # Raise an error on page load if there are pending migrations. 38 | config.active_record.migration_error = :page_load 39 | 40 | # Highlight code that triggered database queries in logs. 41 | config.active_record.verbose_query_logs = true 42 | 43 | # Debug mode disables concatenation and preprocessing of assets. 44 | # This option may cause significant delays in view rendering with a large 45 | # number of complex assets. 46 | config.assets.debug = true 47 | 48 | # Suppress logger output for asset requests. 49 | config.assets.quiet = true 50 | 51 | # Raises error for missing translations. 52 | # config.action_view.raise_on_missing_translations = true 53 | 54 | # Use an evented file watcher to asynchronously detect changes in source code, 55 | # routes, locales, etc. This feature depends on the listen gem. 56 | config.file_watcher = ActiveSupport::EventedFileUpdateChecker 57 | end 58 | -------------------------------------------------------------------------------- /config/webpacker.yml: -------------------------------------------------------------------------------- 1 | # Note: You must restart bin/webpack-dev-server for changes to take effect 2 | 3 | default: &default 4 | source_path: app/javascript 5 | source_entry_path: packs 6 | public_root_path: public 7 | public_output_path: packs 8 | cache_path: tmp/cache/webpacker 9 | check_yarn_integrity: false 10 | webpack_compile_output: true 11 | 12 | # Additional paths webpack should lookup modules 13 | # ['app/assets', 'engine/foo/app/assets'] 14 | resolved_paths: [] 15 | 16 | # Reload manifest.json on all requests so we reload latest compiled packs 17 | cache_manifest: false 18 | 19 | # Extract and emit a css file 20 | extract_css: false 21 | 22 | static_assets_extensions: 23 | - .jpg 24 | - .jpeg 25 | - .png 26 | - .gif 27 | - .tiff 28 | - .ico 29 | - .svg 30 | - .eot 31 | - .otf 32 | - .ttf 33 | - .woff 34 | - .woff2 35 | 36 | extensions: 37 | - .mjs 38 | - .js 39 | - .sass 40 | - .scss 41 | - .css 42 | - .module.sass 43 | - .module.scss 44 | - .module.css 45 | - .png 46 | - .svg 47 | - .gif 48 | - .jpeg 49 | - .jpg 50 | 51 | development: 52 | <<: *default 53 | compile: true 54 | 55 | # Verifies that correct packages and versions are installed by inspecting package.json, yarn.lock, and node_modules 56 | check_yarn_integrity: true 57 | 58 | # Reference: https://webpack.js.org/configuration/dev-server/ 59 | dev_server: 60 | https: false 61 | host: localhost 62 | port: 3035 63 | public: localhost:3035 64 | hmr: false 65 | # Inline should be set to true if using HMR 66 | inline: true 67 | overlay: true 68 | compress: true 69 | disable_host_check: true 70 | use_local_ip: false 71 | quiet: false 72 | pretty: false 73 | headers: 74 | 'Access-Control-Allow-Origin': '*' 75 | watch_options: 76 | ignored: '**/node_modules/**' 77 | 78 | 79 | test: 80 | <<: *default 81 | compile: true 82 | 83 | # Compile test packs to a separate directory 84 | public_output_path: packs-test 85 | 86 | production: 87 | <<: *default 88 | 89 | # Production depends on precompilation of packs prior to booting for performance. 90 | compile: false 91 | 92 | # Extract and emit a css file 93 | extract_css: true 94 | 95 | # Cache manifest.json for performance 96 | cache_manifest: true 97 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | git_source(:github) { |repo| "https://github.com/#{repo}.git" } 3 | 4 | ruby '2.6.6' 5 | 6 | # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' 7 | gem 'rails', '~> 6.0.3' 8 | # Use sqlite3 as the database for Active Record 9 | gem 'sqlite3', '~> 1.4' 10 | # Use Puma as the app server 11 | gem 'puma', '~> 4.1' 12 | # Use SCSS for stylesheets 13 | gem 'sass-rails', '>= 6' 14 | # Transpile app-like JavaScript. Read more: https://github.com/rails/webpacker 15 | gem 'webpacker', '~> 4.0' 16 | # Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks 17 | gem 'turbolinks', '~> 5' 18 | # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder 19 | gem 'jbuilder', '~> 2.7' 20 | # Use Active Model has_secure_password 21 | # gem 'bcrypt', '~> 3.1.7' 22 | 23 | # Use Active Storage variant 24 | gem 'image_processing', '~> 1.2' 25 | 26 | # Reduces boot times through caching; required in config/boot.rb 27 | gem 'bootsnap', '>= 1.4.2', require: false 28 | gem 'hamlit-rails', '~> 0.2.3' 29 | gem 'omniauth', '~> 1.9.1' 30 | gem 'omniauth-github', '~> 1.4.0' 31 | gem 'omniauth-rails_csrf_protection', '~> 0.1.2' 32 | gem 'rails-i18n', '~> 6.0.0' 33 | gem 'active_storage_validations', '~> 0.8.8' 34 | gem 'kaminari', '~> 1.2.0' 35 | gem 'searchkick', '~> 4.3.0' 36 | 37 | group :development, :test do 38 | # Call 'byebug' anywhere in the code to stop execution and get a debugger console 39 | gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] 40 | gem 'factory_bot_rails' 41 | end 42 | 43 | group :development do 44 | # Access an interactive console on exception pages or by calling 'console' anywhere in the code. 45 | gem 'web-console', '>= 3.3.0' 46 | gem 'listen', '~> 3.2' 47 | # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring 48 | gem 'spring' 49 | gem 'spring-watcher-listen', '~> 2.0.0' 50 | 51 | gem 'rubocop', require: false 52 | gem 'rubocop-performance', require: false 53 | gem 'rubocop-rails', require: false 54 | gem 'brakeman' 55 | gem 'rack-mini-profiler', require: false 56 | end 57 | 58 | group :test do 59 | # Adds support for Capybara system testing and selenium driver 60 | gem 'capybara', '>= 2.15' 61 | gem 'selenium-webdriver' 62 | # Easy installation and use of web drivers to run system tests with browsers 63 | gem 'webdrivers' 64 | gem 'simplecov', require: false 65 | end 66 | 67 | # Windows does not include zoneinfo files, so bundle the tzinfo-data gem 68 | gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby] 69 | -------------------------------------------------------------------------------- /app/views/events/show.html.haml: -------------------------------------------------------------------------------- 1 | %h1.mt-3.mb-3= @event.name 2 | .row 3 | .col-8 4 | .card.mb-2 5 | - if @event.image.attached? 6 | = image_tag @event.image, class: "card-img-top" 7 | .card.mb-2 8 | %h5.card-header イベント内容 9 | .card-body 10 | %p.card-text= @event.content 11 | .card.mb-2 12 | %h5.card-header 開催時間 13 | .card-body 14 | %p.card-text= "#{l(@event.start_at, format: :long)} - #{l(@event.end_at, format: :long)}" 15 | .card.mb-2 16 | %h5.card-header 開催場所 17 | .card-body 18 | %p.card-text= @event.place 19 | .card.mb-2 20 | %h5.card-header 主催者 21 | .card-body 22 | - if @event.owner 23 | = link_to(url_for_github(@event.owner), class: "card-link") do 24 | = image_tag @event.owner.image_url, width: 50, height: 50 25 | = "@#{@event.owner.name}" 26 | - else 27 | 退会したユーザです 28 | .col-4 29 | - if @event.created_by?(current_user) 30 | = link_to "イベントを編集する", edit_event_path(@event), class: "btn btn-info btn-lg btn-block" 31 | = link_to "イベントを削除する", event_path(@event), class: "btn btn-danger btn-lg btn-block", method: :delete, data: { confirm: "本当に削除しますか?" } 32 | - if @ticket 33 | = link_to "参加をキャンセルする", event_ticket_path(@event, @ticket), method: :delete, class: "btn btn-warning btn-lg btn-block" 34 | - elsif logged_in? 35 | %button.btn.btn-primary.btn-lg.btn-block{ "data-toggle" => "modal", "data-target" => "#createTicket" } 36 | 参加する 37 | %div.modal.fade#createTicket 38 | .modal-dialog 39 | .modal-content 40 | .modal-header 41 | %h4.modal-title#dialogHeader 参加コメント 42 | %button.close{ type: "button", "data-dismiss" => "modal" } × 43 | = form_with(model: @event.tickets.build, url: event_tickets_path(@event)) do |f| 44 | .modal-body 45 | #createTicketErrors 46 | = f.text_field :comment, class: "form-control" 47 | .modal-footer 48 | %button.btn.btn-default{ type: "button", "data-dismiss" => "modal" } 49 | キャンセル 50 | = f.button "送信", class: "btn btn-primary" 51 | - else 52 | = link_to "参加する", new_event_ticket_path(@event), class: "btn btn-primary btn-lg btn-block" 53 | %hr 54 | .card.mb-2 55 | %h5.card-header 参加者 56 | %ul.list-group.list-group-flush 57 | - @tickets.each do |ticket| 58 | %li.list-group-item 59 | - if ticket.user 60 | = link_to(url_for_github(ticket.user), class: "card-link") do 61 | = image_tag ticket.user.image_url, width: 20, height: 20 62 | = "@#{ticket.user.name}" 63 | = ticket.comment 64 | - else 65 | 退会したユーザです -------------------------------------------------------------------------------- /db/schema.rb: -------------------------------------------------------------------------------- 1 | # This file is auto-generated from the current state of the database. Instead 2 | # of editing this file, please use the migrations feature of Active Record to 3 | # incrementally modify your database, and then regenerate this schema definition. 4 | # 5 | # This file is the source Rails uses to define your schema when running `rails 6 | # db:schema:load`. When creating a new database, `rails db:schema:load` tends to 7 | # be faster and is potentially less error prone than running all of your 8 | # migrations from scratch. Old migrations may fail to apply correctly if those 9 | # migrations use external dependencies or application code. 10 | # 11 | # It's strongly recommended that you check this file into your version control system. 12 | 13 | ActiveRecord::Schema.define(version: 2020_07_07_093324) do 14 | 15 | create_table "active_storage_attachments", force: :cascade do |t| 16 | t.string "name", null: false 17 | t.string "record_type", null: false 18 | t.integer "record_id", null: false 19 | t.integer "blob_id", null: false 20 | t.datetime "created_at", null: false 21 | t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id" 22 | t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true 23 | end 24 | 25 | create_table "active_storage_blobs", force: :cascade do |t| 26 | t.string "key", null: false 27 | t.string "filename", null: false 28 | t.string "content_type" 29 | t.text "metadata" 30 | t.bigint "byte_size", null: false 31 | t.string "checksum", null: false 32 | t.datetime "created_at", null: false 33 | t.index ["key"], name: "index_active_storage_blobs_on_key", unique: true 34 | end 35 | 36 | create_table "events", force: :cascade do |t| 37 | t.bigint "owner_id" 38 | t.string "name", null: false 39 | t.string "place", null: false 40 | t.datetime "start_at", null: false 41 | t.datetime "end_at", null: false 42 | t.text "content", null: false 43 | t.datetime "created_at", precision: 6, null: false 44 | t.datetime "updated_at", precision: 6, null: false 45 | t.index ["owner_id"], name: "index_events_on_owner_id" 46 | end 47 | 48 | create_table "tickets", force: :cascade do |t| 49 | t.integer "user_id" 50 | t.integer "event_id", null: false 51 | t.string "comment" 52 | t.datetime "created_at", precision: 6, null: false 53 | t.datetime "updated_at", precision: 6, null: false 54 | t.index ["event_id", "user_id"], name: "index_tickets_on_event_id_and_user_id", unique: true 55 | t.index ["user_id"], name: "index_tickets_on_user_id" 56 | end 57 | 58 | create_table "users", force: :cascade do |t| 59 | t.string "provider", null: false 60 | t.string "uid", null: false 61 | t.string "name", null: false 62 | t.string "image_url", null: false 63 | t.datetime "created_at", precision: 6, null: false 64 | t.datetime "updated_at", precision: 6, null: false 65 | t.index ["provider", "uid"], name: "index_users_on_provider_and_uid", unique: true 66 | end 67 | 68 | add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id" 69 | add_foreign_key "tickets", "events" 70 | end 71 | -------------------------------------------------------------------------------- /bin/bundle: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'bundle' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "rubygems" 12 | 13 | m = Module.new do 14 | module_function 15 | 16 | def invoked_as_script? 17 | File.expand_path($0) == File.expand_path(__FILE__) 18 | end 19 | 20 | def env_var_version 21 | ENV["BUNDLER_VERSION"] 22 | end 23 | 24 | def cli_arg_version 25 | return unless invoked_as_script? # don't want to hijack other binstubs 26 | return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update` 27 | bundler_version = nil 28 | update_index = nil 29 | ARGV.each_with_index do |a, i| 30 | if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN 31 | bundler_version = a 32 | end 33 | next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/ 34 | bundler_version = $1 35 | update_index = i 36 | end 37 | bundler_version 38 | end 39 | 40 | def gemfile 41 | gemfile = ENV["BUNDLE_GEMFILE"] 42 | return gemfile if gemfile && !gemfile.empty? 43 | 44 | File.expand_path("../../Gemfile", __FILE__) 45 | end 46 | 47 | def lockfile 48 | lockfile = 49 | case File.basename(gemfile) 50 | when "gems.rb" then gemfile.sub(/\.rb$/, gemfile) 51 | else "#{gemfile}.lock" 52 | end 53 | File.expand_path(lockfile) 54 | end 55 | 56 | def lockfile_version 57 | return unless File.file?(lockfile) 58 | lockfile_contents = File.read(lockfile) 59 | return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/ 60 | Regexp.last_match(1) 61 | end 62 | 63 | def bundler_version 64 | @bundler_version ||= 65 | env_var_version || cli_arg_version || 66 | lockfile_version 67 | end 68 | 69 | def bundler_requirement 70 | return "#{Gem::Requirement.default}.a" unless bundler_version 71 | 72 | bundler_gem_version = Gem::Version.new(bundler_version) 73 | 74 | requirement = bundler_gem_version.approximate_recommendation 75 | 76 | return requirement unless Gem::Version.new(Gem::VERSION) < Gem::Version.new("2.7.0") 77 | 78 | requirement += ".a" if bundler_gem_version.prerelease? 79 | 80 | requirement 81 | end 82 | 83 | def load_bundler! 84 | ENV["BUNDLE_GEMFILE"] ||= gemfile 85 | 86 | activate_bundler 87 | end 88 | 89 | def activate_bundler 90 | gem_error = activation_error_handling do 91 | gem "bundler", bundler_requirement 92 | end 93 | return if gem_error.nil? 94 | require_error = activation_error_handling do 95 | require "bundler/version" 96 | end 97 | return if require_error.nil? && Gem::Requirement.new(bundler_requirement).satisfied_by?(Gem::Version.new(Bundler::VERSION)) 98 | warn "Activating bundler (#{bundler_requirement}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_requirement}'`" 99 | exit 42 100 | end 101 | 102 | def activation_error_handling 103 | yield 104 | nil 105 | rescue StandardError, LoadError => e 106 | e 107 | end 108 | end 109 | 110 | m.load_bundler! 111 | 112 | if m.invoked_as_script? 113 | load Gem.bin_path("bundler", "bundle") 114 | end 115 | -------------------------------------------------------------------------------- /config/environments/production.rb: -------------------------------------------------------------------------------- 1 | Rails.application.configure do 2 | # Settings specified here will take precedence over those in config/application.rb. 3 | 4 | # Code is not reloaded between requests. 5 | config.cache_classes = true 6 | 7 | # Eager load code on boot. This eager loads most of Rails and 8 | # your application in memory, allowing both threaded web servers 9 | # and those relying on copy on write to perform better. 10 | # Rake tasks automatically ignore this option for performance. 11 | config.eager_load = true 12 | 13 | # Full error reports are disabled and caching is turned on. 14 | config.consider_all_requests_local = false 15 | config.action_controller.perform_caching = true 16 | 17 | # Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"] 18 | # or in config/master.key. This key is used to decrypt credentials (and other encrypted files). 19 | # config.require_master_key = true 20 | 21 | # Disable serving static files from the `/public` folder by default since 22 | # Apache or NGINX already handles this. 23 | config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present? 24 | 25 | # Compress CSS using a preprocessor. 26 | # config.assets.css_compressor = :sass 27 | 28 | # Do not fallback to assets pipeline if a precompiled asset is missed. 29 | config.assets.compile = false 30 | 31 | # Enable serving of images, stylesheets, and JavaScripts from an asset server. 32 | # config.action_controller.asset_host = 'http://assets.example.com' 33 | 34 | # Specifies the header that your server uses for sending files. 35 | # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache 36 | # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX 37 | 38 | # Store uploaded files on the local file system (see config/storage.yml for options). 39 | config.active_storage.service = :local 40 | 41 | # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. 42 | # config.force_ssl = true 43 | 44 | # Use the lowest log level to ensure availability of diagnostic information 45 | # when problems arise. 46 | config.log_level = :debug 47 | 48 | # Prepend all log lines with the following tags. 49 | config.log_tags = [ :request_id ] 50 | 51 | # Use a different cache store in production. 52 | # config.cache_store = :mem_cache_store 53 | 54 | # Use a real queuing backend for Active Job (and separate queues per environment). 55 | # config.active_job.queue_adapter = :resque 56 | # config.active_job.queue_name_prefix = "awesome_events_production" 57 | 58 | # Enable locale fallbacks for I18n (makes lookups for any locale fall back to 59 | # the I18n.default_locale when a translation cannot be found). 60 | config.i18n.fallbacks = true 61 | 62 | # Send deprecation notices to registered listeners. 63 | config.active_support.deprecation = :notify 64 | 65 | # Use default logging formatter so that PID and timestamp are not suppressed. 66 | config.log_formatter = ::Logger::Formatter.new 67 | 68 | # Use a different logger for distributed setups. 69 | # require 'syslog/logger' 70 | # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name') 71 | 72 | if ENV["RAILS_LOG_TO_STDOUT"].present? 73 | logger = ActiveSupport::Logger.new(STDOUT) 74 | logger.formatter = config.log_formatter 75 | config.logger = ActiveSupport::TaggedLogging.new(logger) 76 | end 77 | 78 | # Do not dump schema after migrations. 79 | config.active_record.dump_schema_after_migration = false 80 | 81 | # Inserts middleware to perform automatic connection switching. 82 | # The `database_selector` hash is used to pass options to the DatabaseSelector 83 | # middleware. The `delay` is used to determine how long to wait after a write 84 | # to send a subsequent read to the primary. 85 | # 86 | # The `database_resolver` class is used by the middleware to determine which 87 | # database is appropriate to use based on the time delay. 88 | # 89 | # The `database_resolver_context` class is used by the middleware to set 90 | # timestamps for the last write to the primary. The resolver uses the context 91 | # class timestamps to determine how long to wait before reading from the 92 | # replica. 93 | # 94 | # By default Rails will store a last write timestamp in the session. The 95 | # DatabaseSelector middleware is designed as such you can define your own 96 | # strategy for connection switching and pass that into the middleware through 97 | # these configuration options. 98 | # config.active_record.database_selector = { delay: 2.seconds } 99 | # config.active_record.database_resolver = ActiveRecord::Middleware::DatabaseSelector::Resolver 100 | # config.active_record.database_resolver_context = ActiveRecord::Middleware::DatabaseSelector::Resolver::Session 101 | end 102 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | actioncable (6.0.3.2) 5 | actionpack (= 6.0.3.2) 6 | nio4r (~> 2.0) 7 | websocket-driver (>= 0.6.1) 8 | actionmailbox (6.0.3.2) 9 | actionpack (= 6.0.3.2) 10 | activejob (= 6.0.3.2) 11 | activerecord (= 6.0.3.2) 12 | activestorage (= 6.0.3.2) 13 | activesupport (= 6.0.3.2) 14 | mail (>= 2.7.1) 15 | actionmailer (6.0.3.2) 16 | actionpack (= 6.0.3.2) 17 | actionview (= 6.0.3.2) 18 | activejob (= 6.0.3.2) 19 | mail (~> 2.5, >= 2.5.4) 20 | rails-dom-testing (~> 2.0) 21 | actionpack (6.0.3.2) 22 | actionview (= 6.0.3.2) 23 | activesupport (= 6.0.3.2) 24 | rack (~> 2.0, >= 2.0.8) 25 | rack-test (>= 0.6.3) 26 | rails-dom-testing (~> 2.0) 27 | rails-html-sanitizer (~> 1.0, >= 1.2.0) 28 | actiontext (6.0.3.2) 29 | actionpack (= 6.0.3.2) 30 | activerecord (= 6.0.3.2) 31 | activestorage (= 6.0.3.2) 32 | activesupport (= 6.0.3.2) 33 | nokogiri (>= 1.8.5) 34 | actionview (6.0.3.2) 35 | activesupport (= 6.0.3.2) 36 | builder (~> 3.1) 37 | erubi (~> 1.4) 38 | rails-dom-testing (~> 2.0) 39 | rails-html-sanitizer (~> 1.1, >= 1.2.0) 40 | active_storage_validations (0.8.8) 41 | rails (>= 5.2.0) 42 | activejob (6.0.3.2) 43 | activesupport (= 6.0.3.2) 44 | globalid (>= 0.3.6) 45 | activemodel (6.0.3.2) 46 | activesupport (= 6.0.3.2) 47 | activerecord (6.0.3.2) 48 | activemodel (= 6.0.3.2) 49 | activesupport (= 6.0.3.2) 50 | activestorage (6.0.3.2) 51 | actionpack (= 6.0.3.2) 52 | activejob (= 6.0.3.2) 53 | activerecord (= 6.0.3.2) 54 | marcel (~> 0.3.1) 55 | activesupport (6.0.3.2) 56 | concurrent-ruby (~> 1.0, >= 1.0.2) 57 | i18n (>= 0.7, < 2) 58 | minitest (~> 5.1) 59 | tzinfo (~> 1.1) 60 | zeitwerk (~> 2.2, >= 2.2.2) 61 | addressable (2.7.0) 62 | public_suffix (>= 2.0.2, < 5.0) 63 | ast (2.4.1) 64 | bindex (0.8.1) 65 | bootsnap (1.4.6) 66 | msgpack (~> 1.0) 67 | brakeman (4.8.2) 68 | builder (3.2.4) 69 | byebug (11.1.3) 70 | capybara (3.33.0) 71 | addressable 72 | mini_mime (>= 0.1.3) 73 | nokogiri (~> 1.8) 74 | rack (>= 1.6.0) 75 | rack-test (>= 0.6.3) 76 | regexp_parser (~> 1.5) 77 | xpath (~> 3.2) 78 | childprocess (3.0.0) 79 | concurrent-ruby (1.1.6) 80 | crass (1.0.6) 81 | docile (1.3.2) 82 | elasticsearch (7.6.0) 83 | elasticsearch-api (= 7.6.0) 84 | elasticsearch-transport (= 7.6.0) 85 | elasticsearch-api (7.6.0) 86 | multi_json 87 | elasticsearch-transport (7.6.0) 88 | faraday (~> 1) 89 | multi_json 90 | erubi (1.9.0) 91 | factory_bot (6.0.2) 92 | activesupport (>= 5.0.0) 93 | factory_bot_rails (6.0.0) 94 | factory_bot (~> 6.0.0) 95 | railties (>= 5.0.0) 96 | faraday (1.0.1) 97 | multipart-post (>= 1.2, < 3) 98 | ffi (1.13.1) 99 | globalid (0.4.2) 100 | activesupport (>= 4.2.0) 101 | hamlit (2.11.0) 102 | temple (>= 0.8.2) 103 | thor 104 | tilt 105 | hamlit-rails (0.2.3) 106 | actionpack (>= 4.0.1) 107 | activesupport (>= 4.0.1) 108 | hamlit (>= 1.2.0) 109 | railties (>= 4.0.1) 110 | hashie (4.1.0) 111 | i18n (1.8.3) 112 | concurrent-ruby (~> 1.0) 113 | image_processing (1.10.3) 114 | mini_magick (>= 4.9.5, < 5) 115 | ruby-vips (>= 2.0.17, < 3) 116 | jbuilder (2.10.0) 117 | activesupport (>= 5.0.0) 118 | jwt (2.2.1) 119 | kaminari (1.2.1) 120 | activesupport (>= 4.1.0) 121 | kaminari-actionview (= 1.2.1) 122 | kaminari-activerecord (= 1.2.1) 123 | kaminari-core (= 1.2.1) 124 | kaminari-actionview (1.2.1) 125 | actionview 126 | kaminari-core (= 1.2.1) 127 | kaminari-activerecord (1.2.1) 128 | activerecord 129 | kaminari-core (= 1.2.1) 130 | kaminari-core (1.2.1) 131 | listen (3.2.1) 132 | rb-fsevent (~> 0.10, >= 0.10.3) 133 | rb-inotify (~> 0.9, >= 0.9.10) 134 | loofah (2.6.0) 135 | crass (~> 1.0.2) 136 | nokogiri (>= 1.5.9) 137 | mail (2.7.1) 138 | mini_mime (>= 0.1.1) 139 | marcel (0.3.3) 140 | mimemagic (~> 0.3.2) 141 | method_source (1.0.0) 142 | mimemagic (0.3.5) 143 | mini_magick (4.10.1) 144 | mini_mime (1.0.2) 145 | mini_portile2 (2.4.0) 146 | minitest (5.14.1) 147 | msgpack (1.3.3) 148 | multi_json (1.14.1) 149 | multi_xml (0.6.0) 150 | multipart-post (2.1.1) 151 | nio4r (2.5.2) 152 | nokogiri (1.10.10) 153 | mini_portile2 (~> 2.4.0) 154 | oauth2 (1.4.4) 155 | faraday (>= 0.8, < 2.0) 156 | jwt (>= 1.0, < 3.0) 157 | multi_json (~> 1.3) 158 | multi_xml (~> 0.5) 159 | rack (>= 1.2, < 3) 160 | omniauth (1.9.1) 161 | hashie (>= 3.4.6) 162 | rack (>= 1.6.2, < 3) 163 | omniauth-github (1.4.0) 164 | omniauth (~> 1.5) 165 | omniauth-oauth2 (>= 1.4.0, < 2.0) 166 | omniauth-oauth2 (1.6.0) 167 | oauth2 (~> 1.1) 168 | omniauth (~> 1.9) 169 | omniauth-rails_csrf_protection (0.1.2) 170 | actionpack (>= 4.2) 171 | omniauth (>= 1.3.1) 172 | parallel (1.19.2) 173 | parser (2.7.1.4) 174 | ast (~> 2.4.1) 175 | public_suffix (4.0.5) 176 | puma (4.3.5) 177 | nio4r (~> 2.0) 178 | rack (2.2.3) 179 | rack-mini-profiler (2.0.1) 180 | rack (>= 1.2.0) 181 | rack-proxy (0.6.5) 182 | rack 183 | rack-test (1.1.0) 184 | rack (>= 1.0, < 3) 185 | rails (6.0.3.2) 186 | actioncable (= 6.0.3.2) 187 | actionmailbox (= 6.0.3.2) 188 | actionmailer (= 6.0.3.2) 189 | actionpack (= 6.0.3.2) 190 | actiontext (= 6.0.3.2) 191 | actionview (= 6.0.3.2) 192 | activejob (= 6.0.3.2) 193 | activemodel (= 6.0.3.2) 194 | activerecord (= 6.0.3.2) 195 | activestorage (= 6.0.3.2) 196 | activesupport (= 6.0.3.2) 197 | bundler (>= 1.3.0) 198 | railties (= 6.0.3.2) 199 | sprockets-rails (>= 2.0.0) 200 | rails-dom-testing (2.0.3) 201 | activesupport (>= 4.2.0) 202 | nokogiri (>= 1.6) 203 | rails-html-sanitizer (1.3.0) 204 | loofah (~> 2.3) 205 | rails-i18n (6.0.0) 206 | i18n (>= 0.7, < 2) 207 | railties (>= 6.0.0, < 7) 208 | railties (6.0.3.2) 209 | actionpack (= 6.0.3.2) 210 | activesupport (= 6.0.3.2) 211 | method_source 212 | rake (>= 0.8.7) 213 | thor (>= 0.20.3, < 2.0) 214 | rainbow (3.0.0) 215 | rake (13.0.1) 216 | rb-fsevent (0.10.4) 217 | rb-inotify (0.10.1) 218 | ffi (~> 1.0) 219 | regexp_parser (1.7.1) 220 | rexml (3.2.4) 221 | rubocop (0.87.1) 222 | parallel (~> 1.10) 223 | parser (>= 2.7.1.1) 224 | rainbow (>= 2.2.2, < 4.0) 225 | regexp_parser (>= 1.7) 226 | rexml 227 | rubocop-ast (>= 0.1.0, < 1.0) 228 | ruby-progressbar (~> 1.7) 229 | unicode-display_width (>= 1.4.0, < 2.0) 230 | rubocop-ast (0.1.0) 231 | parser (>= 2.7.0.1) 232 | rubocop-performance (1.7.0) 233 | rubocop (>= 0.82.0) 234 | rubocop-rails (2.6.0) 235 | activesupport (>= 4.2.0) 236 | rack (>= 1.1) 237 | rubocop (>= 0.82.0) 238 | ruby-progressbar (1.10.1) 239 | ruby-vips (2.0.17) 240 | ffi (~> 1.9) 241 | rubyzip (2.3.0) 242 | sass-rails (6.0.0) 243 | sassc-rails (~> 2.1, >= 2.1.1) 244 | sassc (2.4.0) 245 | ffi (~> 1.9) 246 | sassc-rails (2.1.2) 247 | railties (>= 4.0.0) 248 | sassc (>= 2.0) 249 | sprockets (> 3.0) 250 | sprockets-rails 251 | tilt 252 | searchkick (4.3.0) 253 | activemodel (>= 5) 254 | elasticsearch (>= 6) 255 | hashie 256 | selenium-webdriver (3.142.7) 257 | childprocess (>= 0.5, < 4.0) 258 | rubyzip (>= 1.2.2) 259 | simplecov (0.18.5) 260 | docile (~> 1.1) 261 | simplecov-html (~> 0.11) 262 | simplecov-html (0.12.2) 263 | spring (2.1.0) 264 | spring-watcher-listen (2.0.1) 265 | listen (>= 2.7, < 4.0) 266 | spring (>= 1.2, < 3.0) 267 | sprockets (4.0.2) 268 | concurrent-ruby (~> 1.0) 269 | rack (> 1, < 3) 270 | sprockets-rails (3.2.1) 271 | actionpack (>= 4.0) 272 | activesupport (>= 4.0) 273 | sprockets (>= 3.0.0) 274 | sqlite3 (1.4.2) 275 | temple (0.8.2) 276 | thor (1.0.1) 277 | thread_safe (0.3.6) 278 | tilt (2.0.10) 279 | turbolinks (5.2.1) 280 | turbolinks-source (~> 5.2) 281 | turbolinks-source (5.2.0) 282 | tzinfo (1.2.7) 283 | thread_safe (~> 0.1) 284 | unicode-display_width (1.7.0) 285 | web-console (4.0.3) 286 | actionview (>= 6.0.0) 287 | activemodel (>= 6.0.0) 288 | bindex (>= 0.4.0) 289 | railties (>= 6.0.0) 290 | webdrivers (4.4.1) 291 | nokogiri (~> 1.6) 292 | rubyzip (>= 1.3.0) 293 | selenium-webdriver (>= 3.0, < 4.0) 294 | webpacker (4.2.2) 295 | activesupport (>= 4.2) 296 | rack-proxy (>= 0.6.1) 297 | railties (>= 4.2) 298 | websocket-driver (0.7.2) 299 | websocket-extensions (>= 0.1.0) 300 | websocket-extensions (0.1.5) 301 | xpath (3.2.0) 302 | nokogiri (~> 1.8) 303 | zeitwerk (2.3.1) 304 | 305 | PLATFORMS 306 | ruby 307 | 308 | DEPENDENCIES 309 | active_storage_validations (~> 0.8.8) 310 | bootsnap (>= 1.4.2) 311 | brakeman 312 | byebug 313 | capybara (>= 2.15) 314 | factory_bot_rails 315 | hamlit-rails (~> 0.2.3) 316 | image_processing (~> 1.2) 317 | jbuilder (~> 2.7) 318 | kaminari (~> 1.2.0) 319 | listen (~> 3.2) 320 | omniauth (~> 1.9.1) 321 | omniauth-github (~> 1.4.0) 322 | omniauth-rails_csrf_protection (~> 0.1.2) 323 | puma (~> 4.1) 324 | rack-mini-profiler 325 | rails (~> 6.0.3) 326 | rails-i18n (~> 6.0.0) 327 | rubocop 328 | rubocop-performance 329 | rubocop-rails 330 | sass-rails (>= 6) 331 | searchkick (~> 4.3.0) 332 | selenium-webdriver 333 | simplecov 334 | spring 335 | spring-watcher-listen (~> 2.0.0) 336 | sqlite3 (~> 1.4) 337 | turbolinks (~> 5) 338 | tzinfo-data 339 | web-console (>= 3.3.0) 340 | webdrivers 341 | webpacker (~> 4.0) 342 | 343 | RUBY VERSION 344 | ruby 2.6.6p146 345 | 346 | BUNDLED WITH 347 | 2.1.4 348 | --------------------------------------------------------------------------------