sharoa
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    # 【第24週】パRails輪読会🚂 \(2024\-01\-29\~ 2024\-02\-02\) ###### tags: `パRails🚂` - [開催概要](https://hackmd.io/4A_8ahJtQNi5hz713N5Y7w?view) - [パRails輪読会 ノートまとめ](https://hackmd.io/jsgA8Pf_RVioOgSL_VOR4g) - サンプルコード・正誤表:[サポートページ:パーフェクトRuby on Rails【増補改訂版】:|技術評論社](https://gihyo.jp/book/2020/978-4-297-11462-6/support) - **サンプルコードをダウンロードしただけでは、すぐに`rails s`できない可能性が高い**です。 以下のページに環境構築の手順をまとめたので、ドライバーをやってくださるという方は、こちらに沿って環境構築をお願いします🙏 ⏩ [環境構築の手順 2022年版](https://hackmd.io/y7qb2BRMT2Wd4tAtKYObcQ) ⏩ [環境構築の手順 2023年版](https://hackmd.io/3_lnn8_QRD6wEjwFbWcBzQ) 💁‍♀️ [更新の手順 2章編](https://hackmd.io/pZAmF2EjSmyQ38lUtJ_CqA) ## 目次 [TOC] ------ ## 2024\-01\-29(月) ### ファシリ @moegi29 ### ドライバー @sharoa ### 読んだところ 8-3 「落穂ひろい」から 8-3-2 「Rack Middlewareを利用したエラーハンドリング」の途中まで。 PR:https://github.com/PerfectRubyonRails-Rindoku/Perfect_Ruby_on_Rails_Ch6/pull/28 ### 次回 8-3-2 「Rack Middlewareを利用したエラーハンドリング」 403pから。 🚂 ### 学んだこと・感想 - @sharoa - 病み上がり久しぶりの輪読会で、プラスドライバーになって色々とドキドキした。(さらに梅本さんがいらっしゃっていたので余計ドキドキ増) - アプリケーション中に例外が発生した場合に備えて、適切なハンドリングを用意する必要がある。 - Railsには2種類のエラーハンドリングがあって、コントローラーでrescue_fromメソッドを使う方法と、エラーハンドリング用のRack Middlewareを利用する方法。 - 前者の方法では、本通りにするっと進めたのですが、後者の方法で進めなくなり、どうしたもんかという感じだったのですが、梅本さんが教えてくださって解決ができて本当によかった。 - config/application.rbに設定をすると、特定の例外が発生した時にどんなステータスコードを返すか制御できて、この設定を入れないとサーバー側でエラーが発生した時は自動的に500になるとのことです。 - ドライバーをやりながらだったので、あとでもう一度読み返したいと思います。 - そしてpushもあとでします!! - @shodan - エラーハンドリングには2種類。`rescue_from`をコントローラで使う方法と、`Rack Middleware`を利用する。 - `rescue_from`を利用したエラーハンドリングは、「後に」登録したものから順番に判定されることに注意。 - こういうのはなんとなく先からっぽいイメージがあるので気をつけようと思いました。 - `config/routes.rb`に定義されていないURLがリクエストされた場合、エラーはRack Middlewareで発生する。 - そうなると、このエラーはコントローラに到達しないので、↑の方法では通常キャッチできない。 - これをコントローラレベルでキャッチしようとするには、「どのルーティングにも当てはまっていない場合はエラー用のこのアクションへ」という設定を自前で書くということをp401でやった。 - ↑の方法ではなく、Rack Middlewareで発生したエラーの処理を独自で設定するのがp402でやったこと。 - @sugiwe - エラーハンドリングは、記述の順番が大切。(ルーティングとかも順番が大切) - エラーハンドリングには`rescure_from`とRack Middlewareを利用する2つの方法がある。 - 書籍から読み取るとRack Middlewareが上位互換っぽく見えるんだけど、状況に応じて使い分ける方がいいのか?よくわからなかった… - Rack Middlewareで発生したエラー検知が不要であれば`rescue_from`は手軽で良い?→「Rack Middlewareで発生したエラー検知が不要」かどうか、という判断がわからない - 落穂、拾えてない。。。 - @motohiro-mm - エラーハンドリングには2種類 - `rescue_from`を使う方法 - `rescue_from`の順番に気を付ける、後に登録したもの(下に書いてあるもの)から順番に判定する - RackMiddlewareで発生したエラーを検知できない - RackMiddlewareを使う方法 - ActionDispatch::ShowExceptionsでキャッチされた例外はRails.application.config.exceptions_appとして設定されたRackアプリケーションで処理され、デフォルトではActionDispatch::PublicExceptionsのインスタンスが設定される - `config.action_dispatch.rescue_responses`を修正すると独自の例外が発生したときに500以外のエラーを表示できるようになる - routes.rbは上から読み取られていると思っていたのですが、トップページは開けましたね…調べようとおもいます - @moegi29 - Railsには2種類のエラーハンドリング方法がある。 - コントローラで`rescue_from`メソッドを使う方法 - エラーハンドリング用のRackMiddlewareを利用する方法 - rescue_fromは後に登録したものから順番に判定することに注意 - RackMiddlewareで発生したエラーを検知することができない - application.rbに設定を入れるとどのステータスコードを返すか指定できる - @ayu-0505 - エラーハンドリングに`rescue_from`を使う方法がある。後に登録したものから順番に判定する、というのがイメージと真逆でハマりそうだと思った。 - `rescue_from`ではRack Middlewareで発生したエラーをキャッチできない。route.rbで未定義のURLリクエストはコントローラーまでいかないので、ルーティングの最後にキャッチ設定を書いている - Rack Middlewareを利用してエラーハンドリングをする場合は`action_dispatch.rescue_responses`を修正することで使用する。 - 書籍で難しいところがあると、悪戦苦闘しているうちに、混乱してしまいます。梅本さんが状況と目的を整理してくださったので、「今何を確認したくて何が問題か」明確になりました。ありがとうございます。 ------ ## 2024\-01\-30(火) ### ファシリ @motohiro-mm ### ドライバー @sugiwe ### 読んだところ 8-3-2 「Rack Middlewareを利用したエラーハンドリング」 403pから 9-1-1 「CI(継続的インテグレーション)とは?」まで。 PR: ### 次回 9-1-2 「GitHub Actions」から。🚂 ### 学んだこと・感想 - @sharoa - 想定していないエラーである500エラーが発生した時に、開発者に通知する仕組みがある。 - エラーの通知用のgemで有名なのは`exception_notification` - ただ、このgemだとエラーが大量に発生した際の通知が大量に送信されたり、エラーの対応の管理や、特定のエラーは無視するなどの細かい調整が難しい。 - そういう時は外部のWebサービスを利用してエラー情報を管理するのが良いとのこと。 - 使わないルーティングは制限をする。`only`オプションを利用して使うアクションを限定する。 - コラムのgemの選定のお話は、今のところ「へ〜」としか言葉が出ませんが、すごく大事なことだと思うので、きちんと覚えておこうと思いました。 - いつの間にか9章に!! - コードの更新に対して自動でテストを実行させる仕組みをCI(継続的インテグレーション)と呼ぶそうです。 - @sadanora - `config.consider_all_requests_local = false` - 開発環境でも本番同様のエラー画面を表示することができる。 - 自作サービスでエラー画面の表示確認するときもこれを設定した気がします。 - エラーの管理をするWebサービスが色々ある。 - SentryとかRollbarとか - gemの選定 - メンテナンスが滞っているgemは開発の妨げになる - ↑とは観点が違いますが、自分が実現したい機能がすでにライブラリとして存在してないか調べるためにGitHubのプロジェクト色々見て回ったのを思い出しました。 - 気持ち - 最近作ったタスク管理の自分用テンプレートをGitHubにあげようか迷ってる。 - 自分用なのかOSS扱いのつもりなのか、GTDについてもReadmeに書くつもりなのかとか、説明やコンテキスト難しいって思います。 - @moegi29 - 仕事とか個人開発とかでRailsアプリを運用するならSentryなど外部のWebサービスを利用してエラー情報を管理すると良い。 - Webサービスだとエラーの管理がしやすい。 - 使わないルーティングにアクセスされた場合エラーになってしまうのを防ぐため、onlyオプションで利用するアクションを限定する必要がある。 - なんでもgemを利用するのではなく将来的な運用もちゃんと考えて導入する - 有名なgemでもメンテナンスが止まっているものはざらにある - 開発においてのCI(継続的インテグレーション)はコードの更新に対してサーバー側で自動テストを実行させる仕組みのこと - @shodan - 想定していないエラーが起きたことを開発者が知るための手段として、それ用のgemや外部サービスの利用という方法がある。 - リソースフルルーティングでまとめて設定されたけれど実際は使わないアクションのルーティングは、`only`オプションを使って使えないようにしておく。 - 「なんか逆のやつがあったような〜」と思ってたんですが、やはりありました。 - 『:exceptオプションは逆に、生成しないルーティング(またはルーティングのリスト)を指定します。』`resources :photos, except: :destroy` - https://railsguides.jp/routing.html#%E4%BD%9C%E6%88%90%E3%81%95%E3%82%8C%E3%82%8B%E3%83%AB%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0%E3%82%92%E5%88%B6%E9%99%90%E3%81%99%E3%82%8B - CIについて。サーバ側でコードの変更を検知して、自動でテストを実行し、その結果をフィードバックする仕組み。そのためのCIサービスが多数ある。 - チーム開発に参加中ですが、「FlakyなテストのせいでCIがなかなか通らない」みたいなことがよく起きてます(本当はよくない)。 - @sugiwe - エラー通知は外部サービスを使うと便利。 - ルーティングの制限について。コントローラーで設定しているアクションとルーティング設定は、揃えておくと良い。 - 使っていないルーティングを教えてくれるgemがあるらしい?便利そう - gemを導入するときは人気度ともに、メンテナンス頻度などに気を付ける。そしてできればgemのコードを読んで、どんなことをしているのか把握しておくと良い。さらに、小さな機能なら自分で実装しても良い。 - CIは`継続的インテグレーション`。自分としてはCIはデザイン用語で`コーポレートアイデンティティ`を連想するので気をつけようと思った。(前にちょっと混乱したことがあります) - @motohiro-mm - エラーの通知:gemを使うと開発者にエラーを通知できる - Sentry、Rollbarなど - ルーティングで使われているものだけ`only`に含めることで、必要ないルーティングが渡されたときにルーティングで止めてくれるので、コントローラまでさがしにいかなくなる - gemの選定方法 - gem検索:AwesomeRubyのgemリスト、TheRubyToolboxのgem情報をみる - gemの選定基準:人気度、メンテナンスの頻度←大事 - CI(継続的インテグレーション):自動でテストを実行させる仕組み - push時やPR作成時に実行されることが多い ------ ## 2024\-01\-31(水) ### ファシリ @sharoa ### ドライバー @motohiro-mm ### 読んだところ 9-1-2 「GitHub Actions」から 9-1-3 「GitHub ActionsでElasticsearchとそのプラグインを使う」まで。 PR: ### 次回 9-1-4 「イベント告知アプリケーションのCIをGitHub Actionsで実行する」から。🚂 ### 学んだこと・感想 - @igaiga - ついに参加できてよかったです! - もう何もわからなくなっていてあんまり戦力になれずすみません - @sharoa - ↑igaigaさんがいらっしゃってくれただけで嬉しかったです! - ただ、内容がちょうど激ムズのところで、、、、 - せっかくいらっしゃってくれたので何かを聞きたい!!けど、何をどう聞いたらいいのかわからなかったです。。。。。 - とりあえずわかったことは、GitHub ActionsはGitHub上にあるリポジトリでの変更を検知して自動でテストを実行してくれるWebサービスということです。 - `GitHub Actions`  - パブリックリポジトリであれば無料で利用することができる。  - GitHub社が運営しているから、 GitHubのリポジトリがあればすぐに設定ができる。  - 他のCIサービスと比べると新しいサービス  - 大きな仕様変更があるかもしれないけど、裏を返せば開発が活発に進められている「これから」のサービス(になるのかな。) - 色々とmotohiroさんがしてくれたけど、うまく動かなくて、でも時折こんな感じで動いているんだな、という感じもわかって、でも結局よくわからなくて、、、といった状況で終了してしまいました。明日解決できるといいな。 - @sugiwe - GitHub Actionsは、GitHub上にあるリポジトリの変更を検知して自動でテストを実行してくれるサービス。 - 書籍の通りには全然うまく行かなかったけど、なんとなくActionsが走る様子が見られた気がしてちょっと楽しかった(わからないけど…) - 2022年版輪読会も見てきました、直接的なヒントは見つけられず…😭 https://hackmd.io/crDXhcH8R9CX5XbcusgSaQ - igaigaさんが来てくれて嬉しかったです!! - @moegi29 - ついにigaigaさん降臨でうれしかった! - GitHubActionsというものを初めて試せて勉強になりました。ドライバーしてくださったmotohiroさんありがとうございました。 - 本に書かれていた「GitHubでこれから作成するアクション用のリポジトリを用意します」という部分がわからなかったけど、単純に輪読会で使用しているリポジトリPerfectRubyonRails-Rindokuの直下に作るということでOKだった。 - 何が原因でProcess completed with exit code 10.が出るのか気になるところ。。 - @motohiro-mm - igaigaさんきてくださって嬉しかったです!ぜひまたいらしてください〜!🙌 - GitHubActionsを初めて触ってみたけど、結局よく分からず… - elasticsearchのプラグインのリポジトリを作成・設定して置いておくと、それと連動したファイルを持っているリポジトリがpushされたときにCIが実行されるようだった - Actionsがぐるぐるしている様子は見れて、こうやって自動テストしてるのかな、と思えたのは良かったです - awesome_eventsがある階層が書籍よりも一段階下のような気がして自分のGitHubでawesome_eventsとプラグインのリポジトリの階層を合わせてみたところ、`Process completed with exit code 10.`は突破できました。がその先のところでエラーがでてしまい結局うまくいかず… - むずかしい! ----- ## 2024\-02\-01(木) ### ファシリ @sharoa ### ドライバー @moegi29 ### 読んだところ 9-1-4 「イベント告知アプリケーションのCIをGitHub Actionsで実行する」から 9-3-1 「RuboCop」419p 途中まで。 PR: ### 次回 9-3-1 「RuboCop 自動修正をする-Aオプション」から。🚂 ### 学んだこと・感想 - @sharoa - GitHub Actionsはこういうもんなんだ、と思って今回は終わらせたい(私の中で。)でも、こういうサービスがあることは覚えておく。 - ライブラリは新機能追加やバグ修正などで日々更新されていくから、定期的なアップデートが必要。 - 手動`bundle update`でする方法や、利用しているライブラリを定期更新するサービス`Dependabot`というのがある。 - `Dependabot`はブラウザからセットアップできるし、設定ファイルをリポジトリに追加することでも利用できる。 - rubocopはいつも課題の時にお世話になっているgemで、なんだかホッとするw - @sadanora - dependabotを設定しておくと、ライブラリのアップデートを定期的にチェックして自動でPRを作成してくれる。 - 自動テストと組み合わせることで、ライブラリの更新の手間が最小限になる。 - 自作サービスをリリースしてからロクにメンテしてない。dependabotさん入れようかなと思いました。 - 時間が経っていると億劫になるし心配事も増えるので、最初から入れてれば気持ちが楽だったのになーというのを実感中。 - ロボコップのバイオレンス描写は結構トラウマ - @shodan - Dependabotはgemのバージョンが古いものになっていないかをチェックし、自動で`bundle update`されたPRを作成してくれるbot。 - 設定ファイルは`.dependabot/config.yml`。 - 自動作成された更新PRから差分を確認して、問題なければマージする、という作業は人間が行う。 - ここにCIが合わさると、自動でテストが回るので良い、ということ。 - GitHub Actionsについては昨日欠席したので正直わかっていないですが、自作サービスのCIのところでこの本を参考にできそうだと思えていることで十分収穫だなと思っています。 - @motohiro-mm - Gemの定期的なupdateは、手動で更新する他に、定期更新のサービスがある(GitHub Dependabot、Renovateなど) - Dependabotは、bundle updateされたGemのPRが自動で作成され、差分を確認してマージすることでGemの更新作業ができる - 静的解析ツールを利用するとプログラムを実行せずに問題点を調べて分析できる(Rubocop、Brakemanなど) - Rubocop:検査する個々のルールをcopと呼ぶ - 気づいたらぱRailsもあと少しだなぁとしみじみ思いました〜 - @moegi29 - 昨日に引き続きGithubActionsのところを読んでみてなんとなくの認識ができたので忘れないようにしたい。 - Gemのアップデートを怠ると差分が多くなって作業が困難になるので定期的なアップデートは意識して心がけたほうが良い。 - 静的解析ツールにBreakmanというものもある。 - Dependabotを設定してみたけど動作するのか気になるところ。 ----- ## 2024\-02\-02(金) ### ファシリ @moegi29 ### ドライバー @sugiwe ### 読んだところ 9-3-1 419p「RuboCop 自動修正をする-Aオプション」から 423p コラムの手前まで。 PR:https://github.com/PerfectRubyonRails-Rindoku/Perfect_Ruby_on_Rails_Ch6/pull/31 ### 次回 9-3-1 423p コラム「Gitのコミット前フックを利用して検査する」から。🚂 ### 学んだこと・感想 - @sharoa - 今日は終始リラックスして話が聞けました。多分お馴染みの`rubocop`のおかげだと思いますw - `-A`オプションをつけると自動修正してくれる。ただ、望んでいるコードに書き換えてくれるとは限らない。sadanoraサン曰く、unsafeも含む。 - `-a`オプションだと、 safeとマークされたcopのみを対象としてくれる。 - copの種別は覚えておきたいです。 - `-l`オプションはlint copsのみを実行するオプション。 - `-x`オプションはlayout cops種別についての検査を行い、自動的に修正してくれる。 - railsでのrubocopはただインストールするだけではだめ。 - Gemfilsに記入するのと、設定ファイルを作成しないといけない。 - @sugiwe - Rubocopには色々なオプションがある - `-A`:自動修正できるものを全て自動修正 - `-a`:safeなものだけ自動修正 - `-l`:Lint copsだけを実行 - `-x`:Layout copsだけを検査して、自動修正 - `git commit --amend`でコミットメッセージの修正などできる。 - vimは`i`で編集モード、`esc`で編集モード終了、`:wq`で保存して閉じる - @motohiro-mm - rubocopのcopの種別を初めて知りました - rubocopのaオプションはSafeのCopのみを対象に自動修正する(AオプションはUnSafeも含む) - rubocopのxオプションはレイアウト(インデントやスペースの有無)の検査&修正 - rubocopのデフォルトではクラスの上にコメントを書くように言われる(Missing top-level documentation〜) - FBCではfalseになっている - [rubocop\-fjord/config/rubocop\.yml at master · fjordllc/rubocop\-fjord](https://github.com/fjordllc/rubocop-fjord/blob/master/config/rubocop.yml) - `git commit --amend`は以前sadanoraさんに教えていただいて、そこからコミットの修正にめちゃくちゃ使っています。ありがとうございます🙏 - @sadanora - rubocop - `-a`と`-A`の違いをあんまり意識していなかったので確認できてよかったです。 - `-a`はsafeなもののみ修正、`-A`はunsafeなものも含めて修正する - `$ rubocop --help`での説明 - ``` Autocorrection: -a, --autocorrect Autocorrect offenses (only when it's safe). --auto-correct (same, deprecated) --safe-auto-correct (same, deprecated) -A, --autocorrect-all Autocorrect offenses (safe and unsafe). --auto-correct-all (same, deprecated) --disable-uncorrectable Used with --autocorrect to annotate any offenses that do not support autocorrect with `rubocop:todo` comments. ``` - @moegi29 - -aオプションには-a(小文字)だと安全-Aだとunsafeなものも全部修正されるという違いがある。 - rubocopgemに加えて`rubocop-performance gem`と`rubocop-rails gemもGemfile`へ一緒に追加することでRailsアプリ全体をRubocop解析できる - rbenv,versionsの中にlibがありそれぞれのバージョンごとにみているところが違うということがわかった。自分の環境でもみておきたいです。 -----

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully