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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,6 @@ yarn-debug.log*
.yarn-integrity

/config/credentials/production.key

/vendor/bundle
.DS_Store
5 changes: 5 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ group :development, :test do
gem 'byebug', platforms: %i[mri mingw x64_mingw]
gem 'rb-readline'
gem 'rspec-rails'
gem 'capybara', '~> 3.23'
gem 'selenium-webdriver', '4.9.0'
gem 'webdrivers'
end

group :development do
Expand All @@ -69,3 +72,5 @@ end

# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: %i[mingw mswin x64_mingw jruby]

gem 'nokogiri', '1.12.5'
27 changes: 27 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,15 @@ GEM
msgpack (~> 1.0)
builder (3.2.4)
byebug (11.1.3)
capybara (3.39.2)
addressable
matrix
mini_mime (>= 0.1.3)
nokogiri (~> 1.8)
rack (>= 1.6.0)
rack-test (>= 0.6.3)
regexp_parser (>= 1.5, < 3.0)
xpath (~> 3.2)
concurrent-ruby (1.1.9)
crass (1.0.6)
diff-lcs (1.4.4)
Expand Down Expand Up @@ -173,6 +182,7 @@ GEM
mail (2.7.1)
mini_mime (>= 0.1.1)
marcel (1.0.2)
matrix (0.4.2)
method_source (1.0.0)
mini_mime (1.1.2)
minitest (5.14.4)
Expand Down Expand Up @@ -284,6 +294,7 @@ GEM
rubocop (>= 1.7.0, < 2.0)
ruby-progressbar (1.11.0)
ruby2_keywords (0.0.5)
rubyzip (2.3.2)
sass-rails (6.0.0)
sassc-rails (~> 2.1, >= 2.1.1)
sassc (2.4.0)
Expand All @@ -294,6 +305,10 @@ GEM
sprockets (> 3.0)
sprockets-rails
tilt
selenium-webdriver (4.9.0)
rexml (~> 3.2, >= 3.2.5)
rubyzip (>= 1.2.2, < 3.0)
websocket (~> 1.0)
semantic_range (3.0.0)
sorcery (0.16.1)
bcrypt (~> 3.1)
Expand All @@ -318,24 +333,33 @@ GEM
activemodel (>= 6.0.0)
bindex (>= 0.4.0)
railties (>= 6.0.0)
webdrivers (5.2.0)
nokogiri (~> 1.6)
rubyzip (>= 1.3.0)
selenium-webdriver (~> 4.0)
webpacker (5.4.3)
activesupport (>= 5.2)
rack-proxy (>= 0.6.1)
railties (>= 5.2)
semantic_range (>= 2.3.0)
websocket (1.2.9)
websocket-driver (0.7.5)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5)
xpath (3.2.0)
nokogiri (~> 1.8)
zeitwerk (2.5.1)

PLATFORMS
x86_64-darwin-19
x86_64-darwin-22
x86_64-linux

DEPENDENCIES
aws-sdk-s3
bootsnap (>= 1.4.4)
byebug
capybara (~> 3.23)
draper
enum_help
factory_bot_rails
Expand All @@ -345,6 +369,7 @@ DEPENDENCIES
kaminari!
letter_opener_web
listen (~> 3.3)
nokogiri (= 1.12.5)
pg
puma (~> 5.0)
rack-mini-profiler (~> 2.0)
Expand All @@ -356,11 +381,13 @@ DEPENDENCIES
rubocop
rubocop-rails
sass-rails (>= 6)
selenium-webdriver (= 4.9.0)
sorcery
spring
sqlite3 (~> 1.4)
tzinfo-data
web-console (>= 4.1.0)
webdrivers
webpacker (~> 5.0)

RUBY VERSION
Expand Down
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,17 @@ $ bin/rails s
```

## 事業をエンジニアリングしよう提案編の回答は以下に記述してください

【選択した事業側の課題】
直近一年間で、2回以上もくもく会に参加してくれた人は利用者全体の1%のみ。もくもく会で気の合う仲間を見つけられなかったのではないか?

【提案内容】
参加者のレベル別(具体的には、エンジニア経験年数別)でもくもく会を開催できるようにする。
① エンジニア経験の長いユーザーは、似たレベルのユーザーが多い場で知識共有ができるようになる。それによってもくもく会の価値が高まり再参加を見込めるようになる。エンジニア経験の浅いユーザーは、参加する際の心理的ハードルが下がることで、継続的な参加がしやすくなる。
② 運営側は、年数別の選択肢を設けることにより、必然的に経験年数の浅い人が初めて参加することを見込めるようにもなる。

【実装方針】
・もくもく会作成時に参加対象者の指定を必須にする。あらかじめ「3年未満」、「4〜9年」、「10年以上」、「全員」といった選択肢(タグ)を作成しておき、セレクトボックスによってその選択ができるようにする。イベント作成者は、自分が該当する年数か全員かのどちらかを選択した上でイベントを作成する。
・ヘッダーにある検索フォームで、上記で作成した選択肢(タグ)による絞り込み検索ができるようにする。その際、あらかじめすべての選択肢を並べて表示させておき、ユーザーがそのうちの1つを押下すれば該当するイベントの絞り込みができるようにする。このようにタグをあらかじめ表示させておくことによって、そもそもそのような分類でイベントが開催されているという情報を、ユーザーに即座に与えることができる。
・イベント一覧画面に表示されるイベント概要(現在はタイトル, 内容, 開催地, 開催日時, 作成者が表示されている部分)に、参加対象のタグも表示させる
12 changes: 12 additions & 0 deletions app/controllers/followings_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
class FollowingsController < ApplicationController

def create
current_user.follow(params[:user_id])
redirect_back fallback_location: users_path
end

def destroy
current_user.unfollow(params[:user_id])
redirect_back fallback_location: users_path
end
Comment on lines +3 to +11

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

モデルにロジックを寄せられていて良いですね👍

end
2 changes: 1 addition & 1 deletion app/controllers/mypage/profiles_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@ def update
private

def profile_params
params.require(:user).permit(:name, :avatar)
params.require(:user).permit(:name, :avatar,:email, :profile, :hobby)
end
end
4 changes: 4 additions & 0 deletions app/controllers/users_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ def create
end
end

def show
@user = User.find(params[:id])
end

def user_params
params.require(:user).permit(:email, :name, :password, :password_confirmation)
end
Expand Down
13 changes: 13 additions & 0 deletions app/decorators/following_decorator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class FollowingDecorator < Draper::Decorator
delegate_all

# Define presentation-specific methods here. Helpers are accessed through
# `helpers` (aka `h`). You can override attributes, for example:
#
# def created_at
# helpers.content_tag :span, class: 'time' do
# object.created_at.strftime("%a %m/%d/%y")
# end
# end

end
7 changes: 7 additions & 0 deletions app/models/following.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class Following < ApplicationRecord
belongs_to :follower, class_name: "User"
belongs_to :followed, class_name: "User"
validates :follower_id, presence: true
validates :followed_id, presence: true
Comment on lines +2 to +5

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

念のためfollower_idfollowed_idで複合ユニーク制約をつけておくと良さそうです。

validates :follower_id, uniqueness: {scope: :followed_id}
end
16 changes: 16 additions & 0 deletions app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ class User < ApplicationRecord
has_many :notifications, foreign_key: :receiver_id, dependent: :destroy, inverse_of: :sender
has_many :user_notification_timings, dependent: :destroy
has_many :notification_timings, through: :user_notification_timings
has_many :followers, class_name: "Following", foreign_key: "follower_id", dependent: :destroy
has_many :followeds, class_name: "Following", foreign_key: "followed_id", dependent: :destroy
has_many :following_users, through: :followers, source: :followed
has_many :follower_users, through: :followeds, source: :follower
has_one_attached :avatar

validates :password, length: { minimum: 3 }, if: -> { new_record? || changes[:crypted_password] }
Expand Down Expand Up @@ -76,4 +80,16 @@ def allow_attended_to_event_notification?
def allow_liked_event_notification?
notification_timings.liked_event.present?
end

def follow(user_id)
followers.create(followed_id: user_id)
end

def unfollow(user_id)
followers.find_by(followed_id: user_id).destroy
end

def following?(user)
following_users.include?(user)
end
end
2 changes: 1 addition & 1 deletion app/views/events/_attendee.html.erb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<li>
<div class="d-flex align-items-center gap-2 mb-3">
<%= image_tag attendee.decorate.avatar, class: 'rounded-circle avatar-md' %>
<%= attendee.name %>
<%= link_to attendee.name, user_path(attendee) %>
</div>
</li>
2 changes: 1 addition & 1 deletion app/views/events/_event.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
<div class="d-flex align-items-center justify-content-between">
<div class="d-flex align-items-center gap-3">
<%= image_tag event.user.decorate.avatar, class: 'avatar-sm rounded-circle' %>
<%= event.user.name %>
<%= link_to event.user.name, user_path(event.user) %>
</div>
<% if logged_in? %>
<div id="js-event-bookmark-<%= event.id %>">
Expand Down
2 changes: 1 addition & 1 deletion app/views/events/show.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
<div class="card-body">
<div class="d-flex align-items-center gap-3 mb-3">
<%= image_tag @event.user.decorate.avatar, class: 'rounded-circle avatar-lg' %>
<%= @event.user.name %>
<%= link_to @event.user.name, user_path(@event.user) %>
</div>
<div class="p-3 bg-light">
イベント数
Expand Down
8 changes: 8 additions & 0 deletions app/views/mypage/profiles/show.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@
<%= f.label :name, class: 'form-label' %>
<%= f.text_field :name, class: 'form-control', placeholder: 'らんてくん' %>
</div>
<div class="mb-3">
<%= f.label :hobby, class: 'form-label' %>
<%= f.text_field :hobby, class: 'form-control', placeholder: '学習' %>
</div>
<div class="mb-3">
<%= f.label :profile, class: 'form-label' %>
<%= f.text_area :profile, class: 'form-control', placeholder: '今月からWebエンジニアを目指して...' %>
</div>
<div class="col-12">
<!-- Button -->
<%= f.submit class: 'btn btn-primary' %>
Expand Down
11 changes: 11 additions & 0 deletions app/views/users/show.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<h1>ユーザー情報</h1>
<p>name: <%= @user.name %></p>
<p>hobby: <%= @user.hobby %></p>
<p>profile: <%= @user.profile %></p>
<% if logged_in? && current_user != @user %>
<% if current_user.following?(@user) %>
<%= link_to "フォローを外す", user_followings_path(@user.id), method: :delete %>
<% else %>
<%= link_to "フォローする", user_followings_path(@user.id), method: :post %>
<% end %>
<% end %>
9 changes: 8 additions & 1 deletion config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,14 @@
delete 'logout', to: 'sessions#destroy'
get 'signup', to: 'users#new'
post 'signup', to: 'users#create'
resources :users, only: %i[new create]

resources :users, only: %i[new create show] do
member do
get :follows, :followers
end
resource :followings, only: %i[create destroy]
end

resources :events do
collection do
get :future
Expand Down
5 changes: 5 additions & 0 deletions db/migrate/20230622044719_add_hobby_to_users.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddHobbyToUsers < ActiveRecord::Migration[6.1]
def change
add_column :users, :hobby, :string
end
end
5 changes: 5 additions & 0 deletions db/migrate/20230622044750_add_profile_to_users.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class AddProfileToUsers < ActiveRecord::Migration[6.1]
def change
add_column :users, :profile, :string
end
end
13 changes: 13 additions & 0 deletions db/migrate/20230622160718_create_followings.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class CreateFollowings < ActiveRecord::Migration[6.1]
def change
create_table :followings do |t|
t.integer :follower_id
t.integer :followed_id

t.timestamps
end
add_index :followings, :follower_id
add_index :followings, :followed_id
add_index :followings, [:follower_id, :followed_id], unique: true
end
end
14 changes: 13 additions & 1 deletion db/schema.rb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions spec/rails_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
# Prevent database truncation if the environment is production
abort('The Rails environment is running in production mode!') if Rails.env.production?
require 'rspec/rails'

# Add additional requires below this line. Rails is not loaded until this point!

# Requires supporting ruby files with custom matchers and macros, etc, in
Expand All @@ -23,6 +24,7 @@
# require only the support files necessary.
#
# Dir[Rails.root.join('spec', 'support', '**', '*.rb')].sort.each { |f| require f }
Dir[Rails.root.join('spec/support/**/*.rb')].sort.each { |f| require f }

# Checks for pending migrations and applies them before tests are run.
# If you are not using ActiveRecord, you can remove these lines.
Expand Down Expand Up @@ -65,4 +67,5 @@
# config.filter_gems_from_backtrace("gem name")
config.include FactoryBot::Syntax::Methods
config.include Sorcery::TestHelpers::Rails::Request, type: :request
config.include LoginMacros
end
2 changes: 1 addition & 1 deletion spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
# # is tagged with `:focus`, all examples get run. RSpec also provides
# # aliases for `it`, `describe`, and `context` that include `:focus`
# # metadata: `fit`, `fdescribe` and `fcontext`, respectively.
# config.filter_run_when_matching :focus
config.filter_run_when_matching :focus
#
# # Allows RSpec to persist some state between runs in order to support
# # the `--only-failures` and `--next-failure` CLI options. We recommend
Expand Down
5 changes: 5 additions & 0 deletions spec/support/capybara.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
RSpec.configure do |config|
config.before(:each, type: :system) do
driven_by :selenium, using: :headless_chrome, screen_size: [1920, 1080]
end
end
8 changes: 8 additions & 0 deletions spec/support/login_macros.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module LoginMacros
def login(user)
visit login_path
fill_in 'email', with: user.email
fill_in 'password', with: 'password'
click_button 'ログイン'
end
end
Loading