Slide 1

Slide 1 text

成果発表 By ホット・エアー3

Slide 2

Slide 2 text

ちょんの担当分 ● 固定ポスト #9 ● フォロー中のユーザーの最新ポストを表示 #11 ● プロフィールに出身地を追加 #16 ● ユーザー検索 #12 ● ポストの論理削除 #14 ● 「いいね」機能 #18 ● 捨てられたポストの自動削除 ● ハッシュタグ

Slide 3

Slide 3 text

固定ポスト

Slide 4

Slide 4 text

固定ポスト app/controllers/microposts_controller.rb class MicropostsController < ApplicationController before_action :require_login before_action :set_micropost, only: %i[update destroy toggle_pinned] before_action :authorize, only: %i[update destroy toggle_pinned] def toggle_pinned @micropost.toggle(:pinned).save! redirect_to current_user, status: :see_other end end

Slide 5

Slide 5 text

固定ポスト app/models/micropost.rb class Micropost < ApplicationRecord default_scope -> { order(pinned: :desc, created_at: :desc) } after_save :ensure_single_pinned_post, if: -> { saved_change_to_pinned?(from: false, to: true) } private def ensure_single_pinned_post user.microposts.where(pinned: true).where.not(id: id).update_all(pinned: false) end end

Slide 6

Slide 6 text

ユーザー検索

Slide 7

Slide 7 text

ユーザー検索 config/initializers/constants.rb PREFECTURES = %w[ hokkaido aomori iwate ... ].freeze BIRTHPLACES = [*PREFECTURES, 'overseas'].freeze

Slide 8

Slide 8 text

ユーザー検索 app/views/users/index.html.erb <%= form_with url: users_path, method: :get do |f| %> <%= f.text_field :search_query %> <%= f.select :birthplaces, BIRTHPLACES.map { |p| [p.capitalize, p] }, {}, { multiple: true, size: 10 } %> <%= f.submit 'Search' %> <% end %> <% if @users.any? %> <%= will_paginate %>
    <%= render @users %>
<%= will_paginate %> <% else %>

No users found.

<% end %>

Slide 9

Slide 9 text

ユーザー検索 app/models/user.rb class User < ApplicationRecord def self.search_by(query) if query.blank? all else q = "%#{sanitize_sql_like(query)}%" where('name LIKE ?', q).or(where('email LIKE ?', q)) end end end

Slide 10

Slide 10 text

ユーザー検索 app/controllers/users_controller.rb class UsersController < ApplicationController def index @users = if (b = params[:birthplaces]&.without('')).present? User.search_by(params[:search_query]) .where(birthplace: b) .paginate(page: params[:page]) else User.search_by(params[:search_query]) .paginate(page: params[:page]) end end end

Slide 11

Slide 11 text

ポストの論理削除

Slide 12

Slide 12 text

ポストの論理削除 app/controllers/microposts_controller.rb class MicropostsController < ApplicationController before_action :require_login before_action :set_micropost, only: %i[restore destroy] before_action :authorize, only: %i[restore destroy] def restore @micropost.undiscard redirect_back_or_to root_path, flash: { success: 'Micropost restored' } end def destroy @micropost.discard || @micropost.destroy! redirect_back_or_to root_path, status: :see_other, flash: { success: 'Micropost deleted' } end end

Slide 13

Slide 13 text

ポストの論理削除 app/models/micropost.rb class Micropost < ApplicationRecord include Discard::Model before_save -> { update_column(:pinned, false) }, if: -> { will_save_change_to_discarded_at?(from: nil) && pinned_in_database } end

Slide 14

Slide 14 text

捨てられたポストの自動削除 config/schedule.rb env :PATH, ENV['PATH'] set :output, 'log/cron.log' every :day, at: '3:00am' do rake 'microposts:empty_trash' end

Slide 15

Slide 15 text

捨てられたポストの自動削除 lib/tasks/microposts.rake namespace :microposts do desc 'Empty trash' task empty_trash: :environment do destroyed = Micropost.where(discarded_at: ..30.days.ago).destroy_all puts "Destroyed #{destroyed.length} microposts." end end

Slide 16

Slide 16 text

ハッシュタグ

Slide 17

Slide 17 text

ハッシュタグ app/models/micropost.rb class Micropost < ApplicationRecord has_and_belongs_to_many :tags after_save :tag, if: :saved_change_to_content? private def tag tags.clear unless tags.empty? self.tags = content.scan(/(?<=#)[^\s#]+/).uniq.map do |w| Tag.find_or_create_by!(name: w) end end end

Slide 18

Slide 18 text

ハッシュタグ app/helpers/microposts_helper.rb module MicropostsHelper def render_with_hashtags(content) content.gsub(/#[^\s#]+/) do |ht| link_to w, "/microposts/hashtag/#{ht[1..]}" end end end

Slide 19

Slide 19 text

ご清聴ありがとうございました!