-
Notifications
You must be signed in to change notification settings - Fork 71
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Q&AページのQuestion部分を非Vue化した #7439
Q&AページのQuestion部分を非Vue化した #7439
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
変更部分の説明です。
@@ -41,6 +40,6 @@ def update | |||
private | |||
|
|||
def question_params | |||
params.require(:question).permit(:title, :description, :practice_id, :tag_list, :wip) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
非Vue化に伴い、APIを叩いて質問を更新するシナリオは「質問個別ページ上からのタグの編集」のみになりました。
なので、tag_list
以外のパラメータは受け付けないようにしています。
またupdate
アクションから、Newspaperによる通知の処理を削除しました。
この処理は更新によりwip
状態が変更された場合に起こる処理でしたが、そもそもこの変更によりAPIからの更新でwip
の状態が変わることがなくなったため、削除しています。
questions = | ||
case params[:target] | ||
when 'solved' | ||
Question.solved | ||
when 'not_solved' | ||
Question.not_solved.not_wip | ||
else | ||
Question.all | ||
end | ||
questions = Question.by_target(params[:target]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
【行数オーバーのコントローラのリファクタリング】
ここだけではありませんが、show
とupdate
アクションをコントローラに追加したため、クラスの行数が100行を超えRubocopに指摘されるようになったため、既存の処理の一部をリファクタリングし、行数を減らしています。
※厳密にはこのIssueの趣旨に関連する変更ではありませんが、Rubocopに新たな除外項目を増やすのはNGという方針のため、このようなリファクタリングも当PRに含めています。
コントローラ上でcase when
の条件分岐のロジックまで担当するのは責務的に重いのと、solved
などのtarget
による絞り込みは汎用性があると考えられるので、この部分はモデルのスコープに移しています。
if @question.save | ||
Newspaper.publish(:question_create, { question: @question }) | ||
redirect_to @question, notice: notice_message(@question) | ||
redirect_to Redirection.determin_url(self, @question), notice: @question.generate_notice_message(:create) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Redirection.determin_url
は新規作成時・更新時のリダイレクト先を切り替えるクラスメソッドです。
下記のPRでIssueで実装されています。
#6741
def update | ||
set_wip | ||
if @question.update(question_params) | ||
Newspaper.publish(:question_update, { question: @question }) if @question.saved_change_to_wip? | ||
redirect_to Redirection.determin_url(self, @question), notice: @question.generate_notice_message(:update) | ||
else | ||
render :edit | ||
end | ||
end | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
APIで行っていた更新処理を、通常のRailsのコントローラに移しています。
機能的にはAPIでやっていたものと変わりません。
def questions_property | ||
case params[:target] | ||
when 'solved' | ||
QuestionsProperty.new('解決済みのQ&A', '解決済みのQ&Aはありません。') | ||
when 'not_solved' | ||
QuestionsProperty.new('未解決のQ&A', '未解決のQ&Aはありません。') | ||
else | ||
QuestionsProperty.new('全てのQ&A', 'Q&Aはありません。') | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
【行数オーバーのコントローラのリファクタリング】
特定のQuestionモデルのインスタンスに紐づく処理はないけれど、質問という関心ごとには確実に関連している処理のため、Questionのインスタンスメソッドではなくクラスメソッドに移しました。
div(data-vue="QuestionPage" data-vue-current-user-id:number="#{current_user.id}" data-vue-question-id="#{@question.id}") | ||
.question.page-content | ||
= render 'question_header', question: @question | ||
= render 'question_body', question: @question | ||
div(data-vue="QuestionAnswers" data-vue-current-user-id:number="#{current_user.id}" data-vue-question-id="#{@question.id}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
非Vue化で、質問本文の部分のうち、下の機能を各パーシャルに移しています。
- ユーザーアイコン・Watchボタン・ブックマークボタン・タグ ->
question_header
- 質問本文・編集ページへのリンク(「内容修正」)・絵文字リアクション ->
question_body
残った答え部分はQuestionAnsewers
というVueコンポーネントにリネームし、ここから繋げています。
[ | ||
@question.user.login_name, | ||
@non_editable_user_login_name, | ||
User.find_by(admin: true).login_name | ||
].each do |name| | ||
changed_title = "#{name} changed" | ||
token = create_token(name, 'testtest') | ||
patch @path, | ||
params: { question: { title: changed_title } }, | ||
headers: { 'Authorization' => "Bearer #{token}" } | ||
|
||
assert_response :ok | ||
assert_equal changed_title, @question.reload.title | ||
end | ||
token = create_token('hajime', 'testtest') | ||
patch @path, | ||
params: { question: { tag_list: '新規タグ1,新規タグ2' } }, | ||
headers: { 'Authorization' => "Bearer #{token}" } | ||
assert_response :ok | ||
assert_equal %w[新規タグ1 新規タグ2], @question.reload.tag_list |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
質問編集APIのコントローラテストの部分です。
本PRにより、APIのupdateアクションにはタグを編集する機能だけが残るため、テストもそのように修正しています。
|
||
test '.by_target' do | ||
solved_question = questions(:question3) | ||
not_solved_question = questions(:question1) | ||
assert_includes Question.by_target('solved'), solved_question | ||
assert_not_includes Question.by_target('solved'), not_solved_question | ||
|
||
assert_includes Question.by_target('not_solved'), not_solved_question | ||
assert_not_includes Question.by_target('not_solved'), solved_question | ||
|
||
assert_includes Question.by_target(nil), solved_question | ||
assert_includes Question.by_target(nil), not_solved_question | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
【行数オーバーのコントローラのリファクタリング】
コントローラからモデルに移したスコープ・メソッドのテストを追加しています。
click_button '内容修正' | ||
click_link '内容修正' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
非Vue化により、質問を編集する「内容修正」ボタンでRailsのlink_to
を使用するようになったため、タグがbutton
ではなくa
タグに変わっています。
(pages
やreports
のページでも「内容修正」ボタンはa
タグで実装されており、それにあわせています)
この変更により、このボタンをクリックする多くのシステムテストが落ちるようになったため修正しています。
|
||
test 'using file uploading by file selection dialogue in textarea at editing question' do | ||
question = questions(:question3) | ||
visit_with_auth "/questions/#{question.id}", 'komagata' | ||
click_button '内容修正' | ||
|
||
element = first('.a-file-insert') | ||
within element do | ||
assert_selector 'input.js-question-file-input', visible: false | ||
end | ||
assert_equal '.js-question-file-input', find('textarea.a-text-input')['data-input'] | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
このテストは、Vueでの質問編集画面上のテキストエリアでファイルアップロードが機能することを確かめる内容になっています。
- Vueによる質問編集画面がなくなったこと
- Railsの
form
パーシャル上のテキストエリアにおけるこの機能のテストは、一つ上の'using file uploading by file selection dialogue in textarea'
テストで行われていること
この2点を考慮し、本テストは削除しました。
assert_text '質問を更新しました' | ||
assert_text '質問をWIPとして保存しました。' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
フラッシュメッセージについて、JSではなくRailsのみで一貫して処理することになったので、その都合で一部のシナリオのメッセージの文言が変わりました。
フラッシュメッセージを使っているテストが落ちるようになったものは、このような形で修正しています。
文言変更の詳細については、Issueのやりとりをご確認ください。
#7356 (comment)
@SuzukaHori |
@junohm410 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
お疲れさまです!
大変待たせいたしました🙇♀️
- 質問更新・フラッシュの動作を確認しました。バッチリでした👍
その他QA一覧・コメント・タグ・回答数の表示などで一連の操作を確認しましたが、正常に動作しているように見えました。 - 全体的な設計やコードについて
問題ないように見えました!
丁寧にコメントをつけていただき、大変助かりました。ありがとうございます🙏
以下は感想です:
- question-edit.vueの置き換えについて
question/show内の構造について、日報ページなどと一致してDRYになっており、良いと思いました。
question/editのフラッシュメッセージについても、適切に条件分岐されているとように見えました。 - Answer部分を単独で動かすための修正について
vueに詳しくないので自信がないのですが、3回読んでも特に問題はなさそうに見えました。 - ファットコントローラー解消のためのリファクタリングについて
コントローラー→モデルへの移行がいい感じで行われており、テストも追加されていて良いと思いました。
とても細かい部分で、2点ほどコメントしておりますのでご確認をお願いします!(うち一点は単純な疑問です🙇♀️)
|
||
.page-content-header__row | ||
.page-content-header__tags | ||
= react_component('Tags/Tags', { tagsInitialValue: question.tag_list.join(',').to_s, tagsParamName: 'question[tag_list]', tagsInputId: 'question_tag_list', tagsType: 'Question', tagsTypeId: question.id.to_s }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- 1つ目の
to_s
が不要に思えたのですが、いかがでしょうか??
join
の時点で文字列になっているように見えます👀
irb(main):018:0> Question.last.tag_list.join(',')
=> "ruby,rail,Linux"
irb(main):018:0> Question.last.tag_list.join(',').class
=> String
- 2つ目の
to_s
についても、idを文字列に変換しているのを不思議に感じたので、理由を伺いたいです🙇♀️
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ありがとうございます!こちらの引数の渡し方についてはpages
の実装を真似ていたところだったので、細かく見られていないところでした🙇♂️お恥ずかしい限りです。
Reactコンポーネントの部分を含めて、あらためて確認しました。
1つ目のto_sが不要に思えたのですが、いかがでしょうか??
joinの時点で文字列になっているように見えます👀
こちらはおっしゃる通りだと思います。
tagsInitialValue
はその先のコンポーネントでも文字列であることを期待されていますが、Rubyのメソッドチェーンのjoin
の時点で確実に文字列が返ってくるので、このto_s
は不要です。
2つ目のto_sについても、idを文字列に変換しているのを不思議に感じたので、理由を伺いたいです🙇♀️
結論的には、こちらのto_s
はあってもいいと考えました。
fetch(`/api/${tagsType.toLowerCase()}s/${tagsTypeId}`, { |
ここのtagsTypeId
propsは、Tags/Tags
コンポーネントの中で、APIのエンドポイントを指定するのに使われています。
ここでtagsTypeId
が数値型だった場合、暗黙の型変換による文字列結合が起こります。
数値型でもエラーにはならないですが、文字列のエンドポイントを生成する用途と決まっているのであれば、propsで渡すタイミングで確実にto_s
で文字列にしておいてもいいのかなと考えました👀
なので、tagsInitialValue
の方のto_s
のみ外す、という修正がいいかなと考えていますが、いかがでしょうか?
その他の修正の確認含め、ご確認いただけるとありがたいです🙏
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ご説明ありがとうございます!
tagsTypeId
に関して、コンポーネント内で文字列型以外で使う可能性がないのなら、こちらで変換を行なって良いと思いました👍
tagsInitialValue
の方のto_s
のみ外す方向で、修正をお願いします🙏
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ご確認ありがとうございます🙏tagsInitialValue
の方のto_s
のみ外す修正を行いました。
test/system/questions_test.rb
Outdated
within 'form[name=question]' do | ||
fill_in 'question[title]', with: 'テストの質問(修正)' | ||
fill_in 'question[description]', with: 'テストの質問です。(修正)' | ||
find('.choices__inner').click | ||
find('#choices--js-choices-single-select-item-choice-12', text: 'sshdでパスワード認証を禁止にする').click | ||
find('#choices--js-choices-single-select-item-choice-11', text: 'sshdでパスワード認証を禁止にする').click |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
元の「12」だとテストが失敗&「11」にすると成功するのは確認したのですが、なぜこうなるのかわからなかったため、教えていただきたいです🙇♀️
test/fixtures/practices.ymlで、「sshdでパスワード認証を禁止にする」は12番目のデータに見えるので、不思議に思いました。(見る場所が違っていたらすみません🙇♀️)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
こちらの説明が足りていませんでした、すみませんでした🙇♂️
もともと11
に修正していたのは、更新時のフォームから「プラクティス選択なし」という選択肢がなくなったからでした。
(既存の_form
にその選択肢がなく、Vue上の編集画面にのみ独自でその選択肢が実装されていた)
先頭の要素'#choices--js-choices-single-select-item-choice-1'
がこの「プラクティス選択なし」で、それが消えたので、12から11に順番が変わった、というイメージです。
ただ、そもそも「更新画面から『プラクティス選択なし』を消す」のではなく、「新規画面にも同じ選択肢を追加する」という方向がいいような気がしたので、machidaさんに提案の上、実装の方針を変更しました。
#7356 (comment)
PRの概要欄にも説明を足しております。
よってこの部分はもとの「12」に戻しています🙇♂️
代わりに他のテストがまた影響を受けているのですが、その部分は別途コメントを残しておきます。
test/fixtures/practices.ymlで、「sshdでパスワード認証を禁止にする」は12番目のデータに見えるので、不思議に思いました。(見る場所が違っていたらすみません🙇♀️)
こちらですが、プラクティスの並びは必ずしもtest/fixtures/practices.yml
の並びとは一致しない感じのようですね👀
kimura
の所属するコース「Railsプログラマー」には「Mac OS X」などのカテゴリがあり、コースの中のカテゴリの順番がまず決まっていて、その中で個別のプラクティスが並んでいく、のような構造になっています。
たとえばtest/fixtures/practices.yml
の7・8番目にある「vi」に関するプラクティスですが、これは「Vim」というカテゴリに所属し、このカテゴリは「Railsプログラマー」の中ではそこそこ後ろの方のため、「sshdでパスワード認証を禁止にする」よりも後に並びます。
なので、fixtures
の上から12
番目にあった「sshdでパスワード認証を禁止にする」がプラクティス並びでも12番目にあったのは、上記のようなことが積み重なった上でのたまたまということになりそうです😅
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
テストについて
ご説明ありがとうございます🙏🙏
kimuraの所属するコース「Railsプログラマー」には「Mac OS X」などのカテゴリがあり、コースの中のカテゴリの順番がまず決まっていて、その中で個別のプラクティスが並んでいく、のような構造になっています。
なるほど、並び順はカテゴリの順番の影響を受けていて、practices.ymlとは一致しないのですね😳
ご丁寧にありがとうございます、大変勉強になりました!!
「プラクティス選択なし」の追加について
修正ありがとうございます!
新規作成時・更新時ともに「プラクティス選択なし」を選べることを確認しました👍
Docsの「関連プラクティスなし」にはデザインが入っているように見えるので、一応町田さんに確認すると良いかもと思いました👀
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
細かいところまでチェックいただきありがとうございます!
デザインの入り方の違いですが、使用するセレクトボックス拡張のライブラリのデフォルト状態をそのまま使うかどうか、という問題な気がしたので、そのような方向でmachidaさんに相談しました👍
#7439 (comment)
結論としては現状のままでOK(Docsの方で使うライブラリをQ&Aに合わせる)ということになりましたので、こちらへの修正は特に加えていません🙏
3310ec0
to
9b8fbe4
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1度目のレビュー後の修正部分の補足コメントです。
@questions = Question | ||
.by_target(params[:target]) | ||
.by_practice_id(params[:practice_id]) | ||
.by_tag(params[:tag]) | ||
.with_avatar | ||
.includes(:practice, :answers, :tags, :correct_answer) | ||
.order(updated_at: :desc, id: :desc) | ||
.recent |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
【QuestionsControllerのリファクタリング】
by_target
以外にも、paramsから受け取るpractice_id
・タグ名に基づく条件分岐を伴った検索や、直近の質問を並べるクエリメソッドをモデルのスコープに移しました。
また、既存のコードは@questions
をセットする処理の途中でタグの取得などを行なっていたりしましたが、このスコープへの切り出しにより、@questions
のセットを一つのメソッドチェーンにまとめられるようになりました。
移したモデルのスコープのテストも追加しております。
when Question | ||
"#{user.login_name}さんのQ&A「#{practice[:title]}」" | ||
practice_title = practice ? practice[:title] : 'プラクティス選択なし' | ||
"#{user.login_name}さんのQ&A「#{practice_title}」" | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
「プラクティスを選択しない状態かつ、他のユーザーにメンションをした状態でQ&Aを新規作成・更新するとエラーになる」現象への対応です。
#7356 (comment)
= f.select(:practice_id, practice_options_within_course, { selected: params[:practice_id] }, { id: 'js-choices-single-select' }) | ||
- if question.new_record? | ||
= f.select(:practice_id, practice_options_within_course, { selected: params[:practice_id], include_blank: 'プラクティス選択なし' }, { id: 'js-choices-single-select' }) | ||
- else | ||
= f.select(:practice_id, practice_options_within_course, { include_blank: 'プラクティス選択なし' }, { id: 'js-choices-single-select' }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question.new_record?
で分岐しているのは、「プラクティスページの『質問する』ボタンから/questions/new?practice_id=...
に飛んだ時に、自動でプラクティスが選択されている」という機能を維持するためです。
当該機能のテストは以下です。
bootcamp/test/system/questions_test.rb
Lines 201 to 205 in 6dcc837
test 'select practice title when push question button on practice page' do | |
visit_with_auth "/practices/#{practices(:practice23).id}", 'hatsuno' | |
click_on '質問する' | |
assert_text 'rubyをインストールする' | |
end |
フォームに紐づくモデルオブジェクトが新規のものである場合は、pracrtice_id
クエリパラメータがあればそれをもとにプラクティスがセットされ、そうでなければ「プラクティス選択なし」がセットされるようになっています。
更新時は上記のことをケアすることがないため、「プラクティス選択なし」が選択肢の中に用意されることのみ設定しています。
#7356 (comment)
find('#choices--js-choices-single-select-item-choice-6', text: 'Linuxのファイル操作の基礎を覚える').click | ||
find('#choices--js-choices-single-select-item-choice-7', text: 'Linuxのファイル操作の基礎を覚える').click |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
新規作成フォームのプラクティス選択部分の先頭に「プラクティス選択なし」を追加したことにより、既存のプラクティスの並びが一つ後ろにずれました。そのことによる修正です。
9b8fbe4
to
fe9cf3e
Compare
@SuzukaHori |
@junohm410 ご連絡お待ちしております! |
@SuzukaHori |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
修正お疲れさまです、お待たせしました!
再度コードと動作を確認し、「プラクティス選択なし」が選択できること、「プラクティスを選択しない状態かつメンション時」にバグが発生しないことを確認しました👍
3箇所コメントを追加しましたので、お手隙の際にご確認ください🙇♀️
今回も丁寧にコメントをつけていただき、とても助かりました😭🙏
@@ -31,7 +31,7 @@ def show | |||
.where(practice: @question.practice) | |||
.where.not(id: @question.id) | |||
.includes(:correct_answer) | |||
.order(updated_at: :desc, id: :desc) | |||
.recent |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
recent
の名前を見た時、このサイトのような「最新○件のデータを持ってくる」メソッドを想像しました。
リファクタリングに影響がないのならコントローラーにそのまま書くか、メソッド名を具体的に修正するといいかなと思ったのですが、いかがでしょうか??
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
おっしゃる通りで、recent
だと検索&取得のスコープと勘違いしますね😅勉強になります。
取得ではなく並び替えのスコープであることと、更新順であることの2点を具体化させるべきだと思いましたので、latest_update_order
に変えました。
(indexとshowで全く同じ並び替えをしているので、DRY原則に則ってメソッドに切り出す方針はそのままにしました)
|
||
.page-content-header__row | ||
.page-content-header__tags | ||
= react_component('Tags/Tags', { tagsInitialValue: question.tag_list.join(',').to_s, tagsParamName: 'question[tag_list]', tagsInputId: 'question_tag_list', tagsType: 'Question', tagsTypeId: question.id.to_s }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ご説明ありがとうございます!
tagsTypeId
に関して、コンポーネント内で文字列型以外で使う可能性がないのなら、こちらで変換を行なって良いと思いました👍
tagsInitialValue
の方のto_s
のみ外す方向で、修正をお願いします🙏
test/system/questions_test.rb
Outdated
within 'form[name=question]' do | ||
fill_in 'question[title]', with: 'テストの質問(修正)' | ||
fill_in 'question[description]', with: 'テストの質問です。(修正)' | ||
find('.choices__inner').click | ||
find('#choices--js-choices-single-select-item-choice-12', text: 'sshdでパスワード認証を禁止にする').click | ||
find('#choices--js-choices-single-select-item-choice-11', text: 'sshdでパスワード認証を禁止にする').click |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
テストについて
ご説明ありがとうございます🙏🙏
kimuraの所属するコース「Railsプログラマー」には「Mac OS X」などのカテゴリがあり、コースの中のカテゴリの順番がまず決まっていて、その中で個別のプラクティスが並んでいく、のような構造になっています。
なるほど、並び順はカテゴリの順番の影響を受けていて、practices.ymlとは一致しないのですね😳
ご丁寧にありがとうございます、大変勉強になりました!!
「プラクティス選択なし」の追加について
修正ありがとうございます!
新規作成時・更新時ともに「プラクティス選択なし」を選べることを確認しました👍
Docsの「関連プラクティスなし」にはデザインが入っているように見えるので、一応町田さんに確認すると良いかもと思いました👀
@machida レビューでご指摘いただいた問題「選択なし」の選択肢のスタイルが、DocsとQ&Aで異なる。 詳細現在同様の機能を持っているDocsでは、「関連プラクティスを指定しない」の選択肢にスタイルが当たっています。
今回実装したQ&Aでの「プラクティス選択なし」では、以下のようなスタイルになっています。
DocsとQ&Aで、「選択なし」状態を実装するロジックは同じです。 # Docs
= f.select(:practice_id, practice_options(categories), { include_blank: '関連プラクティスを指定しない' }, { class: 'js-select2' })
# Q&A
= f.select(:practice_id, practice_options_within_course, { include_blank: 'プラクティス選択なし' }, { id: 'js-choices-single-select' }) 原因DocsとQ&Aで異なるのは、セレクトボックスを拡張するライブラリの違いです。 Q&Aはもともと
試しにQ&Aの方でも 対応について、私としての意見対応ですが、私個人として今の状態でもわかりやすいかな?とは思っています。 個別にスタイルを当てることも可能だとは思いますので、まずは上記をご確認いただき、もし「プラクティス選択なし」にスタイルを当てる必要があれば、そのご対応をお願いしたく思います🙏 ご確認のほど、何卒よろしくお願いいたします🙏 |
@junohm410 なるほどー、今回はchoices.jsの見た目のままでお願いします🙏select2をchoices.jsに移行するというのも別Issueで対応したいと思います。こちらのIssue作成をお願いしてもいいでしょうか? |
fe9cf3e
to
ff86b95
Compare
@machida
Issueを作成しておきました👍 |
@SuzukaHori |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
お疲れさまです!
修正内容確認しました😊 Issueの作成含め、ありがとうございました🙏
問題ないと思いますので、私からはApproveさせていただきます✨
レビュー中色々と教えていただき、ありがとうございました!shodanさんの調査方法や、コミュニケーションの取り方など、大変勉強になりました🙇♀️🙇♀️
@SuzukaHori @komagata |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
確認させて頂きました。OKです〜🙆♂️
Issue
概要
個別のQ&Aページ(
https://bootcamp.fjord.jp/questions/{id}
)のうち、答え部分を除いた質問本体部分を、Vueコンポーネント(app/javascript/components/question-page.vue
の一部)による実装ではなく、Railsのviewテンプレートによる実装に変更しました。これにより、質問の更新時に
https://bootcamp.fjord.jp/questions/{id}/edit
への画面遷移が発生するようになっています。質問ページ下部の答え部分(AIの答え+投稿された答え)は別Issueで非Vue化するとのことなので、こちらは既存の実装を残しております。
(
app/javascript/components/question-page.vue
の質問部分を省いたコードをリネームし、単体で動くように修正)また、副次的に以下の点が変更されています。
質問作成・更新時のフラッシュメッセージの整理
以下のように整理されています。
過去の状態・詳しい議論の経緯は以下のコメントをご参照ください。
#7356 (comment)
質問作成時にも「プラクティス選択なし」を選べるようにする
質問更新時に選べるようになっていた「プラクティス選択なし」を、質問作成時でも選べるようにしました。
非Vue化で、作成・更新ともに同じ
_form
パーシャルを使うようになったためです。過去の状態・詳しい議論の経緯は以下のコメントをご参照ください。
#7356 (comment)
「プラクティス選択なし」の状態かつ質問本文でユーザーがメンションをされると、メンション通知のタイトルで使われるプラクティス名部分は「プラクティス選択なし」になる
現在の本番環境では、上記の条件で質問が作成・更新されると、存在しない関連プラクティスのタイトルを通知タイトルに使おうとするため、エラーが起こります。
プラクティスが選択されていない質問でのメンション通知は、「プラクティス選択なし」をタイトルとして扱うように変更し、上記のバグを修正しています。
エラーの状態・詳しい議論の経緯は以下のコメントをご参照ください。
#7356 (comment)
作業内容のおおまかなイメージ
変更前のQ&AページのQuestion部分の構成
変更後のQ&AページのQuestion部分の構成
変更後の非同期の部品をRailsのパーシャルに差し替えるのか、Reactに差し替えるのかなどの選択については、非Vueで
scaffold
ライクに実装されているpages
やreports
と合わせることを基準としております。変更確認方法
画面遷移を伴った更新(通常の更新、公開 -> WIP、WIP→公開)・フラッシュメッセージ・「プラクティス選択なし」の追加について、下記の方法でご確認いただけます。
chore/convert-question-section-from-vue-to-slim
をローカルに取り込むkomagata
でログインし、http://localhost:3000/questions/new
にアクセスする。http://localhost:3000/questions/{id}/edit
に遷移したことと、4. で入力した内容がセットされていることを確認する。http://localhost:3000/questions
の一番上にリンクがあると思います)。「プラクティス選択なし」かつメンションをした際にバグが起きないことは以下の方法でご確認いただけます。
kimura
でログインし、質問作成画面にアクセス。@hatsuno
と入力する(hatsunoにメンションを飛ばす)。hatsuno
でログインする。Screenshot
変更前
質問更新時に画面遷移が起こらず、同じページ上で質問本文部分が編集UIに書き換わる。
変更後
質問更新時に
https://bootcamp.fjord.jp/questions/{id}/edit
への遷移が起こる(通常のRailsのscaffold
ライクな動き)。