- 投稿日:2020-03-16T23:41:37+09:00
【MySQL】プログラミング初心者が今まで遭遇したエラーとその解決方法のメモ
こんばんは!スージーです!
なかなか技術ブログが書けずにモヤモヤしていたので、ちょうど良いネタがあり備忘録も兼ねて。MySQLに接続できないエラー
私は度々、MySQLに接続できずに四苦八苦しています。pidファイルないよーとかsocketないよーとか、その度に過去のメモや参考記事をあちこち探しているのでまとめてみようと思います。
参考
- 【MySQL】pid not foundもしくはpermission deniedの対応方法 https://qiita.com/AK4747471/items/36b73edd9d1e666ae0c0
- RailsプロジェクトでMySQLがbundle installできなかった https://qiita.com/akito19/items/e1dc54f907987e688cc0
- Library not loaded: /usr/local/opt/mysql/lib/libmysqlclient.21.dylib (LoadError) https://note.com/shoki_rails/n/nf7b51ba48084
- mysqlのsocketエラーでrailsアプリが起動できない https://qiita.com/fujitora/items/d341c52706d1954cae28
- mysqld_safe A mysqld process already existsが出た時の対処方法 https://www.takafumitaba.com/mysql-already-exists
- MySQLが再起動しなくなったときに行う3つの手順 https://engineer.evisu0414.com/mysql001/
【遭遇率第1位】
Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)
原因:
ざっくり言うとmysql.sockファイルが存在しないから作ってね
解決策:
/tmp直下にmysql.sockを作るmysql.sockファイルがあるか確認 ~ $cd /tmp tmp $ ls mysql.sockがない tmp $ sudo touch mysql.sock tmp $ cd ~ $ sudo mysql.server start ERROR!~~~ startできずエラー発生したら 権限の書き換え(chownでファイルやディレクトリの所有者と所属グループを変更する) ~ $ sudo chown username /tmp/mysql.sock もしくは権限付与 ~ $ sudo chmod 777 /tmp/mysql.sock もう一度mysql起動 ~ $ sudo mysql.server start ...SUCCESS!mysql.sockファイルの作り方は色々あると思いますが、私はこのエラーが起きた時は
touch
コマンドで/tmp/
ファイル直下にmysql.sock
ファイルを直接作ってしまいます。socketファイル作成しても権限がないと怒られる事もあるのでその時はchown
コマンドかchmod
コマンドで権限の書き換えか権限付与してあげて下さい。【遭遇率第2位】
Can't connect to local MySQL server through socket '/tmp/mysql.sock' (38)
原因:
ざっくり言うとpidファイルが存在しないから作ってね
解決策:
/usr/local/var/mysql/直下にlocal.pidファイルを作る~ $ sudo mysql.server start Starting MySQL … ERROR! server quit updating PID file(/usr/local/var/mysql/usernoMacBook-ea.local.pid) pidファイルがあるか確認してみる ~ $ cd /usr/local/var/mysql mysql $ ls usernoMacBook-ea.local.pidがない mysql $ sudo touch usernoMacBook-ea.local.pid mysql $ cd ~ $ sudo mysql.server start ...ERROR!~~/usr/local/var/mysql/username.local.err: Permission denied 権限ないよと怒られたら先ほどのエラーと同様に権限の書き換え(chownでファイルやディレクトリの所有者と所属グループを変更する) ~ $ sudo chown /usr/local/var/mysql/usernoMacBook-ea.local.pid もしくは権限付与 ~ $ sudo chmod 777 /usr/local/var/mysql/usernoMacBook-ea.local.pid もう一度起動してみる ~ $ sudo mysql.server start ...SUCCESS!先ほどと同様にやり方は色々あると思いますが、
pid
ファイルもtouch
コマンドで作ってあげましょう。mysql.sock
のエラーと同様に権限ないよって怒られたら権限の書き換えか権限付与してあげましょう。ここまでのまとめ
ここまで紹介した
mysql.sock
ないよ、~.local.pid
ないよ、権限
ないよ、がMySQL関連エラーの大半を占めていると思います。「/tmpディレクトリってどこ!?」とか「/usrディレクトリなんて知らないよ」って最初は思いましたが、まずはファイルが無い事を確認する為にcd
コマンドで該当ディレクトリまで潜って見てみましょう。【遭遇率第3位】
mysql立ち上がった!と思ったらsafeモードのプロセスが既に存在してますよっていうエラー
原因:
既にMySQLのプロセスが動いている
解決法:
processをkillする~ $ sudo mysql.server start Starting MySQL SUCCESS! ~ $ 200315 13:51:58 mysqld_safe A mysqld process already exists 動いているMySQLプロセスを確認してみる ~ $ ps aux| grep mysqld user 98762 0.0 0.0 4268296 672 s004 S+ 2:00PM 0:00.01 grep mysqld user 98633 0.0 5.4 4929884 450652 ?? S 1:51PM 0:00.46 /usr/local/opt/mysql@5.6/bin/mysqld --basedir=/usr/local/opt/mysql@5.6 --datadir=/usr/local/var/mysql --plugin-dir=/usr/local/opt/mysql@5.6/lib/plugin --log-error=usernoMacBook-ea.local.err --pid-file= usernoMacBook-ea.local.pid user 98536 0.0 0.0 4281052 1128 ?? S 1:51PM 0:00.03 /bin/sh /usr/local/opt/mysql@5.6/bin/mysqld_safe --datadir=/usr/local/var/mysql ←注目 mysqld_safeプロセスが動いている模様 プロセスをkillする ~ $ sudo kill -9 98536 Password: 一度mysqlを停止する ~ $ mysql.server stop Shutting down MySQL .. SUCCESS! もう一度MySQLを起動してみる ~ $ mysql.server start Starting MySQL . SUCCESS!これはこの前初めて遭遇したエラーです。頻出エラーより遭遇確率は低いと感じますが、
grep
してmysql_safe
のプロセスが動いているか確認しましょう。mysql_safe
以外のプロセスをkillしてもエラー解消しなかったので悪さしているmysql_safeを見つけてあげましょう。【番外編】
過去に一度でも5.7を起動してしまうと、同じデータを使って5.6を起動すると今までの方法では解決できない場合がある。
この状況は過去に一度dockerでMySQL@5.7で起動した後に開発環境のMySQL@5.6を起動した時に起きた事があります。
この状況になったらMySQLをアンインストールする方法があります。ただし、開発環境で大切なデータがDBに残っている場合は何らかの方法で退避させてあげて下さい(退避方法は割愛します。実践した事ないです)。私は幸いにも開発環境に貴重なデータはないので躊躇無くアンインストールしました。
mysqlをアンインストールします ~ $ brew remove mysql ~ $ brew cleanup 以下のディレクトリ下にはmysql関連ファイルが作成されているので念の為、綺麗に削除しておきます ~ $ sudo rm -rf /usr/local/mysql ~ $ sudo rm -rf /Library/StartupItems/MYSQL ~ $ sudo rm -rf /Library/PreferencePanes/MySQL.prefPane ~ $ sudo rm -rf /Library/Receipts/mysql-.pkg ~ $ sudo rm -rf /usr/local/Cellar/mysql* ~ $ sudo rm -rf /usr/local/bin/mysql* ~ $ sudo rm -rf /usr/local/var/mysql* ~ $ sudo rm -rf /usr/local/etc/my.cnf ~ $ sudo rm -rf /usr/local/share/mysql* ~ $ sudo rm -rf /usr/local/opt/mysql* 最後にver5.6をインストール ~ $ brew install mysql@5.6 インストールが完了したらパス通す $ echo 'export PATH="/usr/local/opt/mysql@5.6/bin:$PATH"' >> ~/.bash_profile .bash_profileの変更を反映 $ source ~/.bash_profile MySQLを起動 ~ $ sudo mysql.server start . SUCCESS!アンインストールしても過去のmysqlファイルがなぜか残っている場合があるので面倒ですけど
rm
コマンドで該当該当ファイルを削除してあげます。完全にクリーンになったMySQLならちゃんと起動してくれます。【番外編2】
rails new project-name -d mysql→ Library not loaded: /usr/local/opt/mysql/lib/libmysqlclient.21.dylib (LoadError)
原因:
mysqlのライブラリーがロードできませんよ
対策:
mysql2をアンインストールしてbundle installproject-name $ bundle exec gem uninstall mysql2 project-name $ bundle install . .. ... Gem::Ext::BuildError: ERROR: Failed to build gem native extension. current directory: /Users/akito/git/media/vendor/bundle/gems/mysql2-0.4.4/ext/mysql2 /Users/akito/.rbenv/versions/2.3.1/bin/ruby -r ./siteconf20160929-55293-192vx35.rb extconf.rb checking for ruby/thread.h... yes checking for rb_thread_call_without_gvl() in ruby/thread.h... yes checking for rb_thread_blocking_region()... no checking for rb_wait_for_single_fd()... yes checking for rb_hash_dup()... yes checking for rb_intern3()... yes ----- Using mysql_config at /usr/local/bin/mysql_config ----- checking for mysql.h... yes checking for errmsg.h... yes checking for mysqld_error.h... yes ----- Don't know how to set rpath on your system, if MySQL libraries are not in path mysql2 may not load ----- ----- Setting libpath to /usr/local/Cellar/mysql/5.7.14/lib ----- creating Makefile To see why this extension failed to compile, please check the mkmf.log which can be found here: /Users/akito/git/media/vendor/bundle/extensions/x86_64-darwin-15/2.3.0-static/mysql2-0.4.4/mkmf.log current directory: /Users/akito/git/media/vendor/bundle/gems/mysql2-0.4.4/ext/mysql2 make "DESTDIR=" clean current directory: /Users/akito/git/media/vendor/bundle/gems/mysql2-0.4.4/ext/mysql2 make "DESTDIR=" compiling client.c compiling infile.c compiling mysql2_ext.c compiling result.c compiling statement.c linking shared-object mysql2/mysql2.bundle ld: library not found for -lssl clang: error: linker command failed with exit code 1 (use -v to see invocation) make: *** [mysql2.bundle] Error 1 make failed, exit code 2 Gem files will remain installed in /Users/akito/git/media/vendor/bundle/gems/mysql2-0.4.4 for inspection. Results logged to /Users/akito/git/media/vendor/bundle/extensions/x86_64-darwin-15/2.3.0-static/mysql2-0.4.4/gem_make.out An error occurred while installing mysql2 (0.4.4), and Bundler cannot continue. Make sure that `gem install mysql2 -v '0.4.4'` succeeds before bundling. 盛大に怒られている...以下の参考記事の通りにやってみます
RailsプロジェクトでMySQLがbundle installできなかった
https://qiita.com/akito19/items/e1dc54f907987e688cc0project-name $ bundle config --local build.mysql2 "--with-ldflags=-L/usr/local/opt/openssl/lib --with-cppflags=-I/usr/local/opt/openssl/include" project-name $ bundle install . .. ... Bundle complete! 18 Gemfile dependencies, 78 gems now installed. Use `bundle info [gemname]` to see where a bundled gem is installed. run bundle exec spring binstub --all * bin/rake: Spring inserted * bin/rails: Spring inserted 正常にbundle install完了したみたい project-name $ rails db:create Created database ‘project-name_development’ Created database ‘ project-name_test’ project-name $ rails db:migrate project-name $ rails s => Booting Puma => Rails 5.2.4.1 application starting in development => Run `rails server -h` for more startup options Puma starting in single mode... * Version 3.12.4 (ruby 2.5.1-p57), codename: Llamas in Pajamas * Min threads: 5, max threads: 5 * Environment: development * Listening on tcp://localhost:3000 Use Ctrl-C to stop きたきたきたーーーー!!!!localhost:3000にアクセスすればいつものrails初期画面が表示されます。MySQLエラーのドツボにハマってrails sでサーバ起動できた時は快感ですね。
【忘れがちなコマンド覚書き】
sudo mysql.server start
→MySQLを立ち上げます
sudo mysql.server stop
→MySQLを停止します
sudo mysql.server restart
→MySQLをstop&startします
sudo mysql.server status
→MySQLの状態を確認します
ps aux| grep mysqld
→MySQLのプロセスを探します
まとめ
以上、私が遭遇したMySQLエラーのまとめでした。自分で何度も遭遇して解決しているうちに遭遇するパターンが同じだったので一覧で見れるようにしておけば後から振り返る時に便利だなと思い久々にQiitaを書いてみました。今回は初めてipadでこの記事を全部書いてみましたが、以外と快適に書けたのでipadとsmart keybord買った甲斐がありました。
終わり
- 投稿日:2020-03-16T23:25:49+09:00
railsタグ検索機能(railsチュートリアル後の機能追加)
はじめに
今回は前回追加した、タグ付機能を利用してタグ検索機能を追加します。
前回の記事(タグ付機能)
https://qiita.com/E6YOteYPzmFGfOD/items/bfffe8c3b31555acd51d作るもの
マイクロポストタグ付機能を利用したタグ検索機能。(題材は自分のポートフォリオです。)
対象読者
railsチュートリアルに機能を追加したい等自分と同じ位のレベルの人を対象としています。
作成の流れ
1.検索フォームの作成
2.コントローラーのアクション作成1.検索フォームの作成
今回は検索フォームをroot_path上に設けます。(自分のポートフォリオがマイクロポストの一覧をroot_path(static_pages/home)に設けているため)
app/views/static_pages/home<%= form_with url: root_path, method: :get, class: '自由に' do %> <%= select_tag :tag_id, options_from_collection_for_select(Tag.all, :id, :name, params[:tag_id]), { prompt: 'タグで絞り込み', class: ,'自由に' onchange: 'submit(this.form);' }%> <% end %>fomr_withを使って検索フォームを作ります。各指定している値を自分なりに説明します。
url: 検索した後に移動するページ。(getメソッド後の移動するページ)
method::get 検索時はゲットメソッドを使用する。(root_urlにゲットアクションを起こすのでstatic_page_contorollerのhomeアクションに飛びます。
)
select_tag: フォームの中でセレクトタグを表示するためのメゾット
select_tag:オブジェクト名(tag_id)URLのクエリ(検索するとURLの?以降に表示されてます)
options_from_collection_for_select(
第1引数:オブジェクトのリスト(Tag.all全件表示)
第2,3引数:取得したリストの表示。順番が大切でid,nameの順にすることによりタグnameを表示する。(idを基準に表示する。逆の順番にするとidの数字だけが表示される。)
第4引数:検索後に表示する値。params[:tag_id]とすることによりURLのクエリからidを取得して検索後もフォームにタグ名を表示します。(第2、第3の引数の値が重要です。)
)
{promt:は何も選択していないときに表示される値です。
onchange:submit(this.form)はJavaScriptを実行できるものでセレクトボックスが選択されたときにこの検索がスタートするようにしています。
}続いてコントローラーです。
app/controllers/static_pages_controller.rb@microposts = params[:tag_id].present? ? Tag.find(params[:tag_id]).microposts : Micropost.all ※ページネーション等に渡してくださいタグ検索が実行されるとparamsでURLのクエリ(tag_id)を取得してfindでテーブルの中を探し関連付けしているのでmicropostsで関連するマイクロポストを取得します。検索されていない場合は全てのマイクロポストを取得するようにしています。
おまけ
URLのクエリとはURL上に表示されている?以降のやつです。
なんちゃら.com/?utf8=✓&tag_id=1
paramsメゾットではgetメゾット時にURLのクエリを取得できます!
※ログを見るとこんな記述もあります。
Parameters: {"utf8"=>"✓", "tag_id"=>"2"}以上でタグ検索機能は完成となります。最後までお読みいただきありがとうございました。
アドバイス等いただけるととても喜びます。次はマイクロポストの検索機能を記事にしたいと思います。
ありがとうございました。
- 投稿日:2020-03-16T23:05:50+09:00
二次元配列の格納方法
こんちは!
今日はrails上で二次元配列の格納方法を記載します。理由
この内容が容易に見当たらなかったため、他の方の助けになればと思います。
一次元配列の格納方法
イメージとしては、[1,2,3,4,5,6]
という風に格納したい場合、railsではコントローラーに以下のように記載するとできます。tests_contoroller.rbdef idex @test = [] #配列の宣言 6.times do |i = 0| #6回読み込ませる、そしてiには0を格納している。iは初期化式 @test[i] = i + 1 #初期化式で宣言したiに1足した数字を各配列に代入している。 i += 1 #iに1を足してはじめに戻る。何もしないままはじめに戻ると同じ配列[0]を六回繰り返すだけだから end # 配列[i]になぜ1を足さないかは、配列の初期値は[0]だから二次元配列の格納方法
次は二次元配列です。
イメージとしては[[1,1],[2,1],[3,1]]
と格納したい場合は以下の通りになります。tests_contoroller.rbdef idex @test = [] #配列の宣言 3.times do |i = 0| #3回読み込ませる、そしてiには0を格納している。iは初期化式 @test[i] = [i + 1,1] i += 1 end@test[i] ←の部分は、一緒です。
その配列の中に、さらに配列を入れるイメージです。
|1|1|
|2|1|
|3|1|これを使った応用で、以下のようなコードが表示が実現できます。
<select name="exp_year" id="exp_year"><option value="">--</option> <option value="2020">20</option> <option value="2021">21</option> <option value="2022">22</option> <option value="2023">23</option> <option value="2024">24</option> <option value="2025">25</option> <option value="2026">26</option> <option value="2027">27</option> <option value="2028">28</option> <option value="2029">29</option> <option value="2030">30</option></select>HTML上表示したいものは、1つめの配列に格納されています。
valueの値は、2つめに格納したものがです。格納例としては、以下の通り
|20|2020|
|21|2021|
|22|2022|
|23|2023|これらは以下のコードをコントローラー側に入力すると、vew側で表示でます。
tests_controller.rbdef index year = 2020 @year = [] 11.times do |i = 0| @year[i] = [year - 2000,year] year += 1 i += 1 end endvewには以下の一文追加してね。
tests/test.html.haml= select_tag 'exp_year',options_for_select((@year),class: "exp_year"),prompt: "--"追加したら以下のように見れるはずです。(CSSは適当に付けてみるとよいでしょう)
以上です!
またこう言った、見当たらなかったものをあり次第、アップしていきます!ほなねー。
- 投稿日:2020-03-16T21:37:50+09:00
Progate無料版をやってみる【Ruby on Rails5 II】
前回の続きになります。
Ruby on Rails5 IIになります。
railsの無料分は今回のレッスンまでになります。Ruby on Rails5 II
投稿一覧ページを作成しよう
・前レッスンと同様に
rails g controller posts indexposts → コントローラー
index → アクションposts.html.erb
posts.scss
posts_controllerが自動で作成され
routes.rbに
get 'posts/index'
が記述される。変数を使って表示しよう
・拡張子
.erb
は<% %>で囲むことで、サーバーサイド処理のように書ける。変数定義、代入
<% post = "test" %>変数の中身を表示
<%= post %>each文で表示しよう
・配列を定義して、each文で要素を一つずつ表示することが可能
・each
の初めに<% %>
を使用して終わりにも<% %>
使用する。煩雑化しそうですね。アクションで変数を定義しよう
・アクション内で定義することが普通。
・@を先頭に付けることで、アクションで定義した変数がViewで使用できる。データベースを用意しよう・テーブルを用意しよう・モデルを確認しよう
・ターミナルでテーブルも作成できちゃう・・・。
・rails g model Post content:text
、rails db:migrate
・app/models/post.rb
が自動生成(モデルクラス)rails consoleを使ってみよう
・ん、ターミナル上にコンソール!?
テーブルに投稿データを保存しよう
・上のコンソールはdbに保存する際に必要となる模様。
post = Post.new(content: "テスト")` post.saveんーかなり独特ですね。
テーブルから1つのデータを取り出す
・んー独特すぎてやばい。
https://shuheitakada.com/rails-database-check
のように確認したい・・・。テーブルから全てのデータを取り出そう
・
posts = Post.all(0)
データベースのデータを表示しよう
・Post.allをアクションの@postsに代入する
View側はpost.content
にする
すると画面表示でDBから持ってきた値を表示できる。共通のレイアウトをまとめよう
・共通のHTMLは
views/layouts/application.html.erb
に記載する。link_toメソッド
・aタグを使用せずとも
<%= link_to('文字', 'パス')
の形でリンクを実現できる。感想
・railsならではのターミナルからのコマンド
・rails consoleのところはいまいちピンときていない・・・。
大規模なDBを作成する際もこれでやるのだろうか・・・。Railsの無料版はここまでなので、次回はPHPをやっていこうと思います。
- 投稿日:2020-03-16T20:53:59+09:00
Twitterログイン機能を搭載したRailsアプリを作る
Twitterログイン機能について学習するため、簡素なテストアプリを作成してみることにしたので、その一連の流れを記しておきます。
大きな流れとしては以下のようになります。
- アプリを作成する
- gem「Devise」を導入
- Twitterにアプリを登録し、key情報を取得
- gem「dotenv-rails」を導入して、セキュリティ強化
- Twitterログイン機能の実装
それでは順番に解説していきます!
アプリを作成する
まずはrails newでアプリを作成します。
$ rails new twitter-login-app作成したアプリのディレクトリへ移動します。
$ cd twitter-login-app「Devise」を追加
ログイン機能を使用するため、Deviseというgemを使用します。
Gemfilegem 'devise'$ bundle installDeviseをインストールします。
$ rails g devise:install Running via Spring preloader in process 807 create config/initializers/devise.rb create config/locales/devise.en.ymlDeviseで使用するViewファイルを作成します。
$ rails g devise:views Running via Spring preloader in process 843 invoke Devise::Generators::SharedViewsGenerator create app/views/devise/shared create app/views/devise/shared/_error_messages.html.erb create app/views/devise/shared/_links.html.erb invoke form_for create app/views/devise/confirmations create app/views/devise/confirmations/new.html.erb create app/views/devise/passwords create app/views/devise/passwords/edit.html.erb create app/views/devise/passwords/new.html.erb create app/views/devise/registrations create app/views/devise/registrations/edit.html.erb create app/views/devise/registrations/new.html.erb create app/views/devise/sessions create app/views/devise/sessions/new.html.erb create app/views/devise/unlocks create app/views/devise/unlocks/new.html.erb invoke erb create app/views/devise/mailer create app/views/devise/mailer/confirmation_instructions.html.erb create app/views/devise/mailer/email_changed.html.erb create app/views/devise/mailer/password_change.html.erb create app/views/devise/mailer/reset_password_instructions.html.erb create app/views/devise/mailer/unlock_instructions.html.erbDeviseを使用するモデルを作成します。
$ rails g devise user Running via Spring preloader in process 886 invoke active_record create db/migrate/20200316050323_devise_create_users.rb create app/models/user.rb invoke test_unit create test/models/user_test.rb create test/fixtures/users.yml insert app/models/user.rb route devise_for :users $ rails db:migrateこれでDeviseに対応したuserモデルが作成されました!
Twitterにアプリを登録し、key情報を取得
Twitterログインを実装するため、Twitter Developersへアプリケーション情報を登録します。
未承認の方は申請の手続きからになります。以下の記事が参考になるかと思います。
Twitter API 登録 (アカウント申請方法) から承認されるまでの手順まとめ ※2019年8月時点の情報
登録の際、webサイトURLを指定する箇所を「localhost:3000」などローカル環境のアドレスにするとエラーが表示され登録することができないので、適当なアドレスを入力しておきます。
callback urlには、http://localhost:3000/users/auth/twitter/callback と追加し、「Allow this application to be used to Sign in with Twitter」のチェックボックスにチェックを入れておきます。
アプリケーション作成後、API keyとAPI secret keyの情報を取得しておきます。
「dotenv」を導入して、セキュリティ強化
Twitetrから取得したAPI keyやAPI secret keyの情報をGitなどに公開してしまうと、悪意のある第三者に利用され、損害が発生してしまうリスクがあります。
そのためこうした知られたくない情報は、非公開な情報として扱う必要があります。
そうした時に便利なのが、「dotenv」というgemです。
Gemfilegem 'dotenv-rails'$bundle installその後、Gemfileと同じ位置に「.env」を作成し、先ほどのkey情報を記述します。
.env# Using Twitter API TWITTER_API_KEY=API key TWITTER_SECRET_KEY=API secret key続いて「.gitignore」を編集します。
ここにファイル名を追加することで、特定のファイルをGitの管理対象から除外することができます。.gitignore# See https://help.github.com/articles/ignoring-files for more about ignoring files. # # If you find yourself ignoring temporary files generated by your text editor # or operating system, you probably want to add a global ignore instead: # git config --global core.excludesfile '~/.gitignore_global' # Ignore bundler config. /.bundle # Ignore the default SQLite database. /db/*.sqlite3 /db/*.sqlite3-journal # Ignore all logfiles and tempfiles. /log/* /tmp/* !/log/.keep !/tmp/.keep # Ignore uploaded files in development /storage/* !/storage/.keep /node_modules /yarn-error.log /public/assets .byebug_history # Ignore master key for decrypting credentials and more. /config/master.key .env #ここを追記Twitterログインの実装
Twitterログインは「Oauth」という認証機能を使用します。
まずは必要なgemをインストールします!
Gemfilegem 'omniauth' gem 'omniauth-twitter'gemをインストールします。
$ bundle install先ほど追加したuserモデルにカラムを追加します。
$ rails g migration AddColumnsToUsers uid:string provider:string Running via Spring preloader in process 91573 invoke active_record create db/migrate/20200316073244_add_columns_to_users.rb $ rails db:migrateconfig/initializers/devise.rbを編集します。
config/initializers/devise.rbDevise.setup do |config| #<省略> # ==> OmniAuth # Add a new OmniAuth provider. Check the wiki for more information on setting # up on your models and hooks. # config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo' config.omniauth :twitter, ENV['TWITTER_API_KEY'], ENV['TWITTER_SECRET_KEY'] #<省略> enduserモデルに:omniauthableを追加します。
user.rbclass User < ApplicationRecord # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable, :omniauthable end続けて以下のメソッドを追加します。
ログインしたアカウントを確認し、初めてログインする場合は新しくアカウントを作成するメソッドになります。user.rbclass User < ApplicationRecord # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable, :omniauthable def self.find_for_oauth(auth) user = User.where(uid: auth.uid, provider: auth.provider).first unless user user = User.create( uid: auth.uid, provider: auth.provider, email: User.dummy_email(auth), password: Devise.friendly_token[0, 20] ) user.save! end current_user = user end private def self.dummy_email(auth) "#{auth.uid}-#{auth.provider}@example.com" end endコールバック処理を行うため、app/controllers/users/omniauth_callbacks_controller.rbというコントローラーを作成します。
app/controllers/users/omniauth_callbacks_controller.rbclass Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController def twitter callback_from :twitter end private def callback_from(provider) provider = provider.to_s @user = User.find_for_oauth(request.env['omniauth.auth']) if @user.persisted? flash[:notice] = I18n.t('devise.omniauth_callbacks.success', kind: provider.capitalize) sign_in_and_redirect @user, event: :authentication else session["devise.#{provider}_data"] = request.env['omniauth.auth'] redirect_to new_user_registration_url end end endルーティングを追加します。
config/routes.rbRails.application.routes.draw do devise_for :users, controllers: { omniauth_callbacks: 'users/omniauth_callbacks' } endログインページ作成
Twitterログイン元のページを作成します。
$rails g controller login indexapp/views/login/index.html.erbに、Twitterログインのリンクなどを追加します。
ログイン時はログアウトのリンクを、ログアウト時はログインのリンクを表示できるようにするため、sessionコントローラーを作成します。
$rails g controller session destroysessionコントローラーを以下のように変更します。
ログイン時に保存されるsession情報を削除し、rootにリダイレクトする処理です。sessions_controller.rbclass SessionsController < ApplicationController def destroy reset_session redirect_to root_path end endログイン成功時は「Hello,world!」の文字が表示されるようにします。
views/login/index.html.erb<% if user_signed_in? %> <%= link_to 'Twitter Logout', sessions_destroy_path %> <% else %> <%= link_to 'Twitter Login', user_twitter_omniauth_authorize_path %> <% end %> <% if user_signed_in? %> Hello, world! <% end %>ルーティングを追加します。
config/routes.rbRails.application.routes.draw do root 'login#index' get 'sessions/destroy' devise_for :users, controllers: { omniauth_callbacks: 'users/omniauth_callbacks' } # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html end実際にログインしてみる
まずはサーバーを起動します。
$cd twitter-login-app $rails slocalhost:3000にアクセス・・・
無事ログインでき、リンク表示もログアウトになっています!
- 投稿日:2020-03-16T20:49:34+09:00
ここから始めます。目標をぶち上げる。
はじめに
えー、どうも、圧倒的初心者。NSパンダまんです。
今回はProgateにて基本的な勉強を終了した完全未経験くそごみの私が、今年の8月か9月までに本気でモダンなイケてるナウいポートフォリオを作り、それを引っさげて渋谷のWEB系自社開発企業に内定をもらうことを目標としたサクセスストーリーブログです。
あと、学んだ言語ですが、一応、、、学習教材が多い
短い期間でアプリケーションが作れる。(らしい。実際作ってないから知らん。)
日本人が創り上げた由緒正しき言語である(日本語での問題解決のテキストも多い)
これらの点からファーストチョイスはRubyを選択しました。
Rubyで基礎を深め、そこから他の言語も学んでいこうって寸法です。あと,,,もしこれをみている変わり者なあなた!!
もしあなたが現在プログラミングを学習していて私と同じようなナウい目標を掲げているのなら、、なんかコメントください。
なんでもいいんです。独学でやってるから寂しいんです。寂しがりやなんです。ここでは私とおんなじような目標をたてて頑張っている方と共に目標に向かって頑張って行きたい。そんな願いも込めて書いているのです。
*なお初心者でありインターネットのイの字もわかっておりませんので訳のわからんことを書いていると思ったらばしばしと叩いていただければと思います。コメント欄にベギラゴン唱えても可です。
progateを一通り学び終え、さあ次なにするかとひたすら考えておりました。
progateをやっているうちはどんどんと湧き出てくる新しい知識をひたすらインプットするだけで良かったのでかなり思考停止していたと思います。それが終わったとき、ふと考えてしまったのです。
「あれっこれ次どうすりゃいいの?」ってね。部活の県大会とかで負けた高校生みたいなもんです。完全に方向性を失いました。
それで色々調べたんですけどなんか、、、よくわかんないんですけど
「RAILS チュートリアル」
ってのを発見したのです。最初なんかの本なのかなって思ってAmazonで調べまくりました。でもなんかサイト?電子書籍?みたいな感じみたい。
んで必死の思いで探して。。。(ググったら一発ででました)
見てみたんですけど。。。。。「えっなにこれくっそ読みづらくね??しかも今まで散々インプットしてきたのにまたインプット?お兄さん疲れちゃったよ。もう簡単なアプリ作りたいよ!!」
と正直思いました。やる気になりませんでしたね。あと、なんか外国の方が作っているのかな?それを翻訳した感じでなんか読みづらい。文系のくせに読解能力に疎い私は簡単に2,3分パラパラとページをみて諦めました。笑
とりあえずチュートリアルをすっ飛ばして簡単なアプリ作る方針に決めました。
そこでわからないことあったらまた戻ってインプットすりゃあええと。というわけで次回は環境構築について書いていきたいと思います!!
それでは!!!!
- 投稿日:2020-03-16T20:37:11+09:00
【Ruby】Nokogiriでカクヨムの作品をダウンロード
前置き
カクヨムというサイトがあります。これは小説家になろうとかノベルアップ+とかハーメルンのような1所謂「小説投稿サイト」の一つです。
私は今月にコミカライズが連載開始予定の名作・超世界転生エグゾドライブ -激闘!異世界全日本大会編-をオフライン保存して読もうと思ったのですが、カクヨムの公式は小説家になろうのように第三者向けにダウンロードの手段を用意してません。
そこで、作品ページを直接スクレイピングして保存することでダウンロードを実現したので、それに使ったプログラムをメモついでに紹介します。注意
- Rubyは殆ど初めて触るので、至らない点も多々あると思われます
- まずないと思いますがこのプログラムを使う場合、自己責任でお願いします。
- 保存したデータは私的利用に留めましょう。他人への譲渡・販売は違法です。
準備
この記事等を参考に、Nokogiriをインストールしておいてください。
作る
入力を受け取る
特段延べるべきこともなく、普通に受け取ります。
Scrape.rbrequire 'nokogiri' require 'open-uri' puts "目次のURLを下さい" get = gets.chomp if ! /https:\/\/kakuyomu.jp\/works\/\d{19}/ === get #入力された文字列がURLの型に合うかを正規表現でチェック while ! /https:\/\/kakuyomu.jp\/works\/\d{19}/ === get puts "目次のURLを下さい" end endもうちょっと短縮できたと思うんですが、どうもエラーが連続しまして…
目次を取得する
カクヨムのURLに関するシステムは、こういう局面においては少しばかり面倒臭いものです。
仮にこれが小説家になろうとかハーメルンとかだったら、ユニークIDは各作品に1つずつ割り振られる他には存在しないため、URLから直接ダウンロードを開始できたでしょう。小説家になろうにおける話数の増え方(例:「シャングリラ・フロンティア~クソゲーハンター、神ゲーに挑まんとす~」)第一話:https://ncode.syosetu.com/n6169dz/1/ 第二話:https://ncode.syosetu.com/n6169dz/2/ 第三話:https://ncode.syosetu.com/n6169dz/3/ 第四話:https://ncode.syosetu.com/n6169dz/4/ 第五話:https://ncode.syosetu.com/n6169dz/5/ですが、カクヨムやノベルアップ+だとそうはいきません。恐らくエピソードの挿入との兼ね合いだと思われるんですが、こいつらは「各作品」とはまた別に「各エピソード」にもユニークIDを設定しているんです。
カクヨムにおける話数の増え方(例:「超世界転生エグゾドライブ -激闘!異世界全日本大会編-」)第一話:https://kakuyomu.jp/works/1177354054884850859/episodes/1177354054884851015 第二話:https://kakuyomu.jp/works/1177354054884850859/episodes/1177354054884853763 第三話:https://kakuyomu.jp/works/1177354054884850859/episodes/1177354054884862727 第四話:https://kakuyomu.jp/works/1177354054884850859/episodes/1177354054884878794 第五話:https://kakuyomu.jp/works/1177354054884850859/episodes/1177354054884886288そういうわけで、カクヨムでは小説家になろうみたいに作品のユニークIDの後ろにつける数字を1ずつ増やしていくだけではダメでして、先に目次を取得する必要があります。
ということで、次のようなコードでぱぱっと取得します。Scrape.rbrequire 'nokogiri' require 'open-uri' #(略) doc = Nokogiri::HTML(URI.open(get)) doc.xpath("//a[@class='widget-toc-episode-episodeTitle']").each do |url| urls.push(url[:href]) #配列「urls」に目次を格納 endディレクトリ周りのあれこれ
プログラムと同じ階層にテキストデータを保存するのはぐちゃぐちゃになる未来が目に見えている選択肢なので、フォルダを新しく作ってその中にダウンロードしたデータを格納しましょう。
Scrape.rbrequire 'nokogiri' #(略) if ! Dir::exist?("Kakuyomu_DL_Data") #既にフォルダを作成済みか判定 Dir::mkdir("Kakuyomu_DL_Data") endそして、作ったフォルダ「Kakuyomu_DL_Data」の下に更にフォルダを作ります。カクヨムのタイトルは被ることもあったと思うので、万が一のフォルダ名の重複を避けるために変化をつけるようにしています。
Scrape.rb#(略) Dir_Path = "Kakuyomu_DL_Data/" + doc.xpath("//h1[@id='workTitle']").inner_text #先ほど読み込んだ目次から作品タイトルを取得 if Dir.exist?(Dir_Path) count = 1 while Dir.exist?("#{Dir_Path}(#{count})") do count += 1 end Dir_Path << "(#{count})" end Dir::mkdir(Dir_Path)各エピソードにアクセスしてダウンロード
いよいよ本文のダウンロードのフェーズです。先ほど作った作品専用フォルダの下に、テキストデータとして一話ずつ作品を保存します。
Scrape.rb#(略) count = 0 size = urls.size urls.each do |url| count += 1 doc = Nokogiri::HTML(URI.open("https://kakuyomu.jp" + url)) File.open("#{Dir_Path}/#{count}.txt","w") do |text| text.puts doc.xpath("//header[@id='contentMain-header']").inner_text #章名とエピソード名 text.puts doc.xpath("//div[@class='widget-episodeBody js-episode-body']").inner_text#本文 end puts "保存中…(#{count}/#{size})" sleep 1 #スクレイピングをするときは、しっかり間隔を置こう! end puts "完了!"ここまでに挙げたコードを連結すれば、カクヨムの目次を投げると全話保存するプログラムができます。
感想
やっぱりRubyはScratchではとてもできないことが色々できますね……
ところでもうちょっとコードが短くできるのでは?(診断メーカー脳)参考サイト等
例として挙げるサイト群の選定について疑問をお持ちの方もいらっしゃるでしょうが、適当に挙げただけですので見逃していただけますと幸いです ↩
- 投稿日:2020-03-16T19:34:44+09:00
refileのattachment_image_tagで画像がうまく表示されない場合に
概要
現在スクールにてRailsの学習中で、画像表示にrefileを使用しましたが、正しく記述しているはずなのに上手く表示されず少し苦労したので備忘録も兼ねて対処法をメモします。(スクールのカリキュラムには後半にちゃんと対処法が書いてありましたが、自分が読み飛ばしてしまい、対処に時間がかかってしまいました。)同じ症状の方の助けになれば幸いです。
環境
OS: macOS Catalina バージョン10.15.3
Ruby: 2.5.7p206
Rails: 5.2.4.1
開発環境:VirtualBox + vagrant前提
こちらの記事にある1〜5のインストール・設定・記述は実施しました。
refileの基本的な使い方が良く纏まっていると拝見いたしましたので、引用させていただきます。
refileの基本と複数画像のアップロードちなみにgemのバージョンは
refile 0.6.2
refile-mini_magick 0.2.0
です。症状
正しく設定・記述されているはずなのにブラウザ上で以下の様になってしまい、画像がうまく表示されませんでした。
- Chrome
- Safari
確認してみたこと、試してみたこと
- データベースの中身の確認
そもそもデータベースのimage_idカラムに保存がされていないのではないかと思い確認。
自分の場合はlistsテーブルにimage_idカラムを設置していたので、rails dbconsoleから
SELECT * FROM listsで全レコードを表示。
image_idカラムを確認しましたが、きちんと文字列が記載されていたのでデータベースへの保存自体はうまくいっている様でした。
- ブラウザの変更
あまり関係ないかもと思いつつ、上記の通りChromeとSafari両方のブラウザで表示状況を確認しましたがどちらも上手く表示されていませんでした。
- 別の拡張子の画像ファイルをアップ
最初に投稿していた画像が.jpgだったので、試しにと思い.pngの画像もアップしてみる。しかしやはり上手く表示されていませんでした。
原因・解決法
結論から言うとattachment_image_tagの書き方が原因でした。
上記のリンク先にもある通り、自分が見た多くの記事ではviewの記述としては
<%= attachment_image_tag モデル名, :カラム名(末尾の_idは除く),format: '拡張子名(例: jpeg)', :fill, 横幅の数値(例: 100), 高さの数値 %>が紹介されていましたが、これの
:fill, 横幅, 高さ
の部分が問題だった様です。
自分の場合は以下の記法に変更して画像が表示される様になりました。<%= attachment_image_tag モデル名, :カラム名(末尾の_idは除く),format: '拡張子名', size: "横幅数値x高さ数値" %>⚠️最後の横幅数値、高さ数値の間の記号は小文字のエックスです。
例:
<%= attachment_image_tag list, :image, format: 'jpeg', size: "100x100" %>これで以下の様に、きちんと表示されるようになりました!
後書き
なぜ
:fill
での指定はダメでsize:
ならいけるのかという原理的な理由は分かりませんでしたが、自分の場合はこれでとりあえず画像がちゃんと表示される様になりました。今後これで進めて行った場合に不具合が出てきたら都度追記していこうと思います。
また、冒頭でも述べた通りスクールのカリキュラム内で、後半にではありましたがきちんと対処法が書かれていました。(自分はそこまでカリキュラムを進めていたので読んでいたはず。)今後は1文字も読み飛ばさず、しっかりと確認しつつ取り組んでいこうと思います!
- 投稿日:2020-03-16T18:56:55+09:00
SpecTest - ビヘイビア駆動開発(BDD)用テスティング・フレームワーク
はじめに
この記事 の続き。SpecTest の内容を少し紹介。まだすぐに使える形ではないですが、要望があれば何とかしたい。...無いか?
気にせずに進みます。こういうのは勢いと思い一気に書いてみました。
ビヘイビア駆動開発では、振る舞いに対するテストを書くことによって動作仕様を明確にしていく。いわゆる Tests as Documentation、Specification by Example というもの。
しかし既存の BDD フレームワークは「テストを書く=それがドキュメント」という図式は成り立つものの、ユーザー向けの説明文書になるかというと、決してそうはなっていない、という問題がある、と私は思う、ような気がする。TDD から派生して、あくまで仕様を理解できる、という点にフォーカスしたモノ。
そこで SpecTest だ。
- SpecTest
- Writing a specification means writing a test, and examples are becoming test codes as is.
- 訳「仕様を書くことはテストを書くこと、で、例はそのままテストになってるんだよ」
Specification by Example はまさにそんな感じ、Tests as Documentation はなんか逆転して Documentation as Tests みたいな感じだが、BDD というくくりの本質である「振る舞い駆動」という意味では間違ってないはず。一応、「今までの BDD テスティング・フレームワークが〇〇な形だから、これは違うよ!」という意見は聞かないことにします...。いや、間違ってないはず。たぶん間違っていないと思う。間違ってないんじゃないかな。ちょっとだけ覚悟しておきます。イメージ的には doctest 系に近いと思うが、よりプログラミングの世界から距離を取っています。書くのはユーザー向けのドキュメント。
恐らく厳密な意味で BDD のこれまでの経緯や定義と照らし合わせると違うとは思うがしかし、理想と現実の間の中で私が欲しいと思うスタイルはこうだった、それは概念として BDD と言って差し支えないだろう、ということは表明しても良いかなー、と思ってます。
まーあまり深く考えないでくださいませませ。
どんな感じ?
- プログラミング言語は問わない(なんでも行ける)
- Markdown で記述
.spectest
に解釈ルールを記載(だが沢山書く必要はない)- (Markdown を解釈して自動的にコードを抽出して)テストしてレポート
そう、書くのは仕様。
プログラミング言語は問わない
作るのはユーザー説明用の Markdown ドキュメントなので、特にプログラミング言語は問わない。あなたの素敵な Ruby で書かれたプロダクトに対しても機能するようにデザインしましたよ。
というか何だったらプログラムじゃなくても Okay だ。
curl
コマンド使って REST API で取ってきた JSON の内容が妥当か、みたいな。Markdown で記述
以下がテンプレート。
# TestSuite Name 最初の `#` で示される表題は自動的にテストスイート名として認識される。 ## なんでも なんでも書ける。 ## なんでも なんでも書ける。 ## Examples `## Examples` はテストコード記述エリア開始のサイン。 テキスト部分はなんでも書ける。 ### Example 1. TestCase Name `### Example [0-9]+\\.` はテストケース開始のサイン。 上記に続く名前がテストケース名になって、1つのテストケースが作られる。 #### Code `#### Code` はテストコード開始のサイン。 でも以下のコードブロックがテスト本体。それ以外は何でも書ける。 ```language Test Code ``` テストコードの結果は標準出力に出すようにすること。 #### Result `#### Result` はテスト期待値開始のサイン。 でも以下のコードブロックが期待値本体。それ以外は何でも書ける。 ``` Expected Result ``` ### Example 2. TestCase Name 2 2 つ目のテストケース。以下略。予め決まったキーワードにさえ気を付けて書けば、テストという意識を持つことなく文書を書ける。キーワードは
.spectest
ファイルで指定も可能。
.spectest
に解釈ルールを記載
.spectest
ファイルのサンプルは以下。詳細は長くなるのでひとまずリンクで... SpecTest の表あたりを参照。{ "root": "doc/spec", "testfile": "test.kx", "resultfile": "result.txt", "interpreter": "kinx", "ignoreFiles": [ "doc/spec/../benchmark/README.md", "doc/spec/spectest/README.md" ] }
root
はドキュメントのあるフォルダ(ディレクトリ)。ここにあるREADME.md
またはCONTENTS.md
をスタート地点として、そこからリンクされている.md
ファイルを全てリストアップして実行する。
testfile
とresultfile
はテストするときに使用する一時ファイル。毎回上書きして最後に消すので既にあるファイルを指定しないこと(要注意)。interpreter
はテストコードを実行するインタプリタ名。コンパイル言語にはまだ対応していない(そんなに難しくないのでできそうだが)。ignoreFiles
はリストアップされてしまうファイルのうち、テスト実行対象外にするファイル名を配列で指定しておく。テストしてレポート
現在(2020/3/16)の Kinx のテスト状況をサンプルにすると、こんな感じになっている。
- 仕様自体は ここ(Kinx 仕様全体) です。
Test Cout = 69 [<>[<*********>][<****>][<***>][<*>][<*>][<***>][<****>][<******>][<**>][<**>][<***>] [<****>][<*****>[W]][<*>][<*>][<*>][<*>][W][W][W][W][W][W][W][W][W][W][W][W][W][W][W] [W][W]] <Test Result Detail> Entry: doc/spec/README.md Kinx Specification with SpecTest (0.00s) Entry: doc/spec/statement/declaration.md Declaration statement (0.55s) Case[0] (Normal case) ........................... successful ( 0.07s) Case[1] (With initializer) ...................... successful ( 0.06s) Case[2] (With initializer of expression) ........ successful ( 0.06s) Case[3] (Multiple variable declaration) ......... successful ( 0.07s) Case[4] (Constant value (1)) .................... successful ( 0.04s) Case[5] (Constant value (2)) .................... successful ( 0.06s) Case[6] (Constant value (3)) .................... successful ( 0.04s) Case[7] (Constant value (4)) .................... successful ( 0.04s) Case[8] (Constant value (5)) .................... successful ( 0.08s) Entry: doc/spec/statement/enum.md Enum statement (0.29s) Case[0] (Normal case) ........................... successful ( 0.07s) Case[1] (With initializer (1)) .................. successful ( 0.07s) Case[2] (With initializer (2)) .................. successful ( 0.07s) Case[3] (The scope) ............................. successful ( 0.07s) Entry: doc/spec/statement/expression.md Expression statement (0.23s) Case[0] (Assignment) ............................ successful ( 0.08s) Case[1] (Exponent Evaluation) ................... successful ( 0.07s) Case[2] (Logical Undefined Operator) ............ successful ( 0.06s) Entry: doc/spec/statement/mixin.md Mixin statement (0.07s) Case[0] (Normal case) ........................... successful ( 0.07s) Entry: doc/spec/statement/block.md Block statement (0.08s) Case[0] (Scope) ................................. successful ( 0.08s) Entry: doc/spec/statement/if_else.md If-Else statement (0.21s) Case[0] (Normal case) ........................... successful ( 0.06s) Case[1] (No else clause) ........................ successful ( 0.06s) Case[2] (If-else combination) ................... successful ( 0.07s) Entry: doc/spec/statement/switch_case.md Switch-Case statement (0.31s) Case[0] (Normal case) ........................... successful ( 0.08s) Case[1] (With do-while) ......................... successful ( 0.07s) Case[2] (Non-integer value) ..................... successful ( 0.08s) Case[3] (Complex switch-case pattern) ........... successful ( 0.07s) Entry: doc/spec/statement/try_catch_finally.md Try-Catch-Finally statement (0.43s) Case[0] (Normal catch) .......................... successful ( 0.07s) Case[1] (Finally (1)) ........................... successful ( 0.07s) Case[2] (Finally (2)) ........................... successful ( 0.06s) Case[3] (Finally (3)) ........................... successful ( 0.07s) Case[4] (Define own exception) .................. successful ( 0.06s) Case[5] (Complex example) ....................... successful ( 0.07s) Entry: doc/spec/statement/while.md While statement (0.14s) Case[0] (Normal case) ........................... successful ( 0.06s) Case[1] (Infinaite loop) ........................ successful ( 0.07s) Entry: doc/spec/statement/do_while.md Do-While statement (0.15s) Case[0] (Normal case) ........................... successful ( 0.07s) Case[1] (Infinaite loop) ........................ successful ( 0.07s) Entry: doc/spec/statement/for.md For statement (0.21s) Case[0] (Normal case) ........................... successful ( 0.07s) Case[1] (Infinaite loop) ........................ successful ( 0.07s) Case[2] (Declation variable in scope) ........... successful ( 0.06s) Entry: doc/spec/statement/return.md Return statement (0.32s) Case[0] (Normal case) ........................... successful ( 0.07s) Case[1] (Without expression) .................... successful ( 0.07s) Case[2] (if-modifier (1)) ....................... successful ( 0.09s) Case[3] (if-modifier (2)) ....................... successful ( 0.08s) Entry: doc/spec/statement/yield.md Return statement (0.36s) Case[0] (Normal case) ........................... successful ( 0.07s) Case[1] (Without expression) .................... successful ( 0.06s) Case[2] (if-modifier (1)) ....................... successful ( 0.08s) Case[3] (if-modifier (2)) ....................... successful ( 0.07s) Case[4] (`yield` returns array.) ................ successful ( 0.07s) Entry(nolink): doc/spec/statement/statement/fiber.md Entry: doc/spec/algorithm/qsort.md Quicksort (0.08s) Case[0] (Quicksort Algorithm) ................... successful ( 0.08s) Entry: doc/spec/algorithm/heapsort.md Heapsort (0.08s) Case[0] (Heapsort Algorithm) .................... successful ( 0.08s) Entry: doc/spec/algorithm/mergesort.md Merge Sort (0.08s) Case[0] (Merge Sort Algorithm) .................. successful ( 0.08s) Entry: doc/spec/algorithm/crc32.md CRC32 (0.08s) Case[0] (CRC32 Algorithm) ....................... successful ( 0.08s) Entry(nolink): doc/spec/statement/throw.md Entry(nolink): doc/spec/statement/function.md Entry(nolink): doc/spec/statement/class.md Entry(nolink): doc/spec/statement/module.md Entry(nolink): doc/spec/statement/lambda.md Entry(nolink): doc/spec/statement/closure.md Entry(nolink): doc/spec/statement/fiber.md Entry(nolink): doc/spec/lib/primitive/integer.md Entry(nolink): doc/spec/lib/primitive/double.md Entry(nolink): doc/spec/lib/primitive/string.md Entry(nolink): doc/spec/lib/primitive/array.md Entry(nolink): doc/spec/lib/basic/file.md Entry(nolink): doc/spec/lib/basic/directory.md Entry(nolink): doc/spec/lib/basic/regex.md Entry(nolink): doc/spec/lib/basic/xml.md Entry(nolink): doc/spec/lib/basic/zip.md Entry(nolink): doc/spec/lib/net/http.md <Test Result> Total Test Cases: 69 Successful : 51 Failed : 0 Warning : 18
Entry(nolink)
はまだドキュメントが書けていないものです。書きます。もちろんテストではなく、仕様(=例)を。おわりに
まだ以下に対応していないので、以下に対応することでもうちょっと実用になると思う。
- Todo
- JUnit 形式の XML で出力する。多分簡単。
- Kinx をまだ簡単にインストールできないので、簡単にインストールできるようにする。それができないと実質使えない。もしくは完全に Kinx から独立させてしまう。
- 履歴を保存しておき、テスト結果の推移を可視化できるようにする。
- CircleCI とかで結果に対するバッチを作れるようにする。
- コンパイル型のプログラミング言語に対応する。
コンセプトに応援してくださる方は(いつもの通り)★をお願いします。やる気出ると思うので。Kinx のほうに。どうしても分離して独立して使えたほうが良いよ、という方(誰に言ってるんだろう...? まぁいいか)は SpecTest のほうに★してくれればそういう意思表示と認識しましょう。
- 最初の動機は スクリプト言語 KINX(ご紹介) を参照してください。
- リポジトリ
- リポジトリは ここ(https://github.com/Kray-G/kinx) です。もし宜しければ★をポチっと。
- SpecTest で独立したリポジトリも用意。ここ(https://github.com/Kray-G/SpecTest) です。ただし、現在は Kinx へのリンクでしかない。どう独立させるかは検討中。
- 投稿日:2020-03-16T17:36:17+09:00
クラスメソッドとインスタンスメソッド
メソッドとは
Rubyにおけるメソッドとは、標準で組み込まれているメソッド(関数)ではなく、ユーザーが独自に定義できる関数のことをメソッドと呼びます。
qiita.rbdef メソッド名 実行する処理 end
- クラスメソッド クラスが使用できるメソッドです。 クラスメソッドを定義したクラス自身が使用できます。クラスで共通の情報を使った処理に使用します。
『クラスメソッド』
qiita.rbclass Qiita def self.page print("こんにちは") end end Qiita.page『実行結果』
qiita.rbこんにちは
- インスタンスメソッド インスタンスが使用できるメソッドです。インスタンスメソッドを定義したクラスのインスタンスに使用できます。インスタンスごとの個別の情報(属性値)を使った処理に使用します。
『インスタンスメソッド』
qiita.rbclass Qiita def page print("Ryo Katsuno") end end instance = Qiita.new instance.page『実行結果』
ruby:qiita.rb
Ryo Katsuno
まとめ
クラスメソッドとインスタンスメソッドの違い
覚えるの大変ですね。。。
- 投稿日:2020-03-16T16:57:16+09:00
部分テンプレートとは?
部分テンプレートってなんなの??
部分テンプレートとは・・・
複数のビューファイルの中で使われている部分を一つのビューファイルとして管理すること。
つまりどういうことかというと複数回使うビューをテンプレート化してしまうことで冗長な記述が必要なくなるというとっても便利かつ簡単なテクニックです。
部分テンプレートを作成する
部分テンプレートのビューを作成するときの注意点としてビューファイルのファイル名の先頭の部分に
_ (アンダーバー)
をつける必要があります。
例えば、呼び出したい部分テンプレートファイルがheader.html.erb
だとすると、
_header.html.erb
と書き換えましょう。部分テンプレートの呼び出し方
当たり前ですが、実際に部分テンプレートを呼び出すためのメソッドがあります。それが
renderメソッド
です._header.html.erbrender 'ファイル名' #'ファイル名'で部分テンプレートの呼び出し render partial: 'ファイル名' #partialはつけてもつけなくても可このように記述していくことで部分テンプレートが使用できて、同じようなコード再度記述していく必要がなくなります!便利ですよね。
haml
で書くとどうなるのかというと_header.html.haml= render 'ファイル名' #=でくくってあげちゃうだけ
renderメソッド
にはもっと活用できるオプションがあるみたいなので詳しく知りたい方は検索してみましょう(優秀なエンジニアに丸投げ)以上です。至らない点があればコメントお願いします。
- 投稿日:2020-03-16T16:15:44+09:00
RubyとPythonにおける、外部ソースコードを読み込む書き方の違い
これは何?
RubyとPythonの両方でプログラムを書いていると、外部ソースコードを読み込む書き方が「どっちがどっちだっけ?」と混乱することがあります。そうした場合に向けての備忘録です。
Rubyの場合
require './foobar'
- モジュール名を含むパス全体を
require
の後に書く- モジュール名を引用符で囲う必要がある
Pythonの場合
from . import foobar
- パス指定でモジュールをインポートする場合、モジュール名を除くパスを、
from
の後・import
の前に書く- モジュール名は
import
の後に書く- モジュール名を引用符で囲う必要はない
Pythonの場合、「パッケージ」やらなんやらの関連概念があるが、今回はそうした項目には触れない。
- 投稿日:2020-03-16T15:39:23+09:00
1行追加のみ! Net::HTTPで発生するcertificate verify failedを回避
外部APIを叩くのに、Docker使っていたらエラーが発生
SSL_connect returned=1 errno=0 state=error: certificate verify failed (self signed certificate in certificate chain)
原因を調べるのに疲れた。
ローカル環境のみで発生するので真面目に対応するのも面倒。
本番はDocker使ってないし。
楽できる方法、探した。解決策1
config/initailizersのファイルに以下を追記する。
OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE if Rails.env.development?参照:Rails5 devise twitterソーシャルログイン ローカル環境でのエラー解消
ただ、これだと、
・サーバー再起動が必要
・ローカル環境のログでalready initialized constant OpenSSL::SSL::VERIFY_PEER
的な警告がうざい
というデメリットがある。もっと楽、したい。
テキトーに生きたい。解決策2
def api(url) uri = URI.parse(url) req = Net::HTTP::Get.new(uri) http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = (uri.scheme == 'https') http.verify_mode = OpenSSL::SSL::VERIFY_NONE # これ追加。 res = http.start { |h| h.request(req) } JSON.parse(res.body) end1行追加で動いた。
テキトーにif分岐追加しても1行で済む。
- 投稿日:2020-03-16T14:32:52+09:00
VSCodeにおいて、インストール済みのlive shareができない場合の対処法(MAC)
先生から送られてきた、liveshareのリンクを踏んでも、collaboration することができませんでした、、
解決策の結論として「GitHub で再認証を行うこと」が必要でした。
VSCodeをメニューバーから強制終了し、再起動を行なった場合は、再度Githubの認証を得る必要があり、以下に手順を示します。
1.VSCodeの下にある、紫色のliveshareと書いてあるバーをクリックする
2.sign in with githubと表示されるのでそれをクリック
3.safariが開き、表示された認証ボタンを押すことで、認証が完了し、liveshareが使える様になる
下のバーに自分のユーザー名が表示されていれば成功です。
- 投稿日:2020-03-16T13:03:02+09:00
外部キー制約のついたカラムを削除したい
外部キー制約の付いたカラムを削除するのにプチハマりしたのでまとめます
参考
こちらの記事でマイグレーションについてかなり詳しくまとめられています
マイグレーションの操作をするときは、こちらの記事で該当箇所をざっと読んでから公式ドキュメントに目を通すのが良さそう
https://pikawaka.com/rails/migrationAPIdoc
https://apidock.com/rails/ActiveRecord/ConnectionAdapters/SchemaStatements/remove_index例)ベストアンサー機能
- questionモデル内に、ベストアンサーに選ばれた回答を保存するためのbestカラムがある
- bestカラムには外部キーが設定してある(answersテーブル)
という状況
db/schema.rbcreate_table "questions", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t| t.bigint "best" t.index ["best"], name: "fk_rails_dd35f91b0c" end add_foreign_key "questions", "answers", column: "best"実践
まずはカラム削除用のマイグレーションファイルを作成する
$rails g migration RemoveBestFromQuestions
マイグレーションファイルが生成
db/migrate/xxxx_remove_best_from_questions.rbclass RemoveBestFromQuestions < ActiveRecord::Migration[5.1] def change end endこちらにカラムを削除するための記述を追加していく
外部キーとインデックスを貼っているので、カラムを削除する記述だけではエラーが発生してしまう
それらを削除する記述も必要っぽいdb/migrate/xxxx_remove_best_from_questions.rbclass RemoveBestFromQuestions < ActiveRecord::Migration[5.1] def change remove_foreign_key :questions, :answers remove_index :questions, :best remove_column :questions, :best, :bigint end endこれで
rails db:migrate
を実行すればOK最後に
間違っている部分があれば遠慮なくご指摘ください
- 投稿日:2020-03-16T12:45:10+09:00
[Rails] Mechanizeがファイルディスクリプタを大量に消費してしまう
内容はタイトル通り。
Railsにて、Mysql2のConnectionError出てる場合とか
ファイルディスクリプタを異常に使いまくってる場合はもしかしたら関係あるかも。経緯
お客様に提供しているサービス(Rails,puma)にて
Mysql2::Error::ConnectionErrorが多発してサービスが利用できなくなる障害が発生しました。
詳しくログを追ってみると他にも
Errno::EMFILE (Too many open files @ rb_sysopen ...(略)のようなエラーも発生している様子。
さらに、、、
# ファイルディスクリプタ上限確認 ulimit -n # pumaプロセスのファイルディスクリプタ確認 for i in $(ps aux | grep "[p]uma" | awk '{print $2}'); do sudo ls /proc/$i/fd | wc -l; done上記コマンドでプロセスの開いてるファイル数を確認してみたら
どうやらファイルディスクリプタがいっぱいになっているようだった。原因
実は、ファイルを開いているわけではなくてアプリケーションで使用していた Mechanize というgemにて
外部からデータを取得する際にコネクションを作成していた様子。
(スクレイピングとかするときに使われてるgemらしい。)ファイルディスクリプタでは、ファイルだけでなくコネクションもカウントされるようで
大量のコネクションが削除されずに作成され続けたことで問題が発生した。
(Mysqlも多分コネクション関係?? 詳しい人コメントお願いします。)対応
単純に、コネクションが開いたままになっていることが問題。
閉じてあげる必要がある。Mechanizeのコネクションは以下のメソッドを呼び出すと閉じてくれるらしいので
使用中のコネクションの最後の処理が終わったあたりで呼び出してあげる。Mechanize.shutdownあとは、サーバー再起動などで既存コネクションを消してあげましょう。
- 投稿日:2020-03-16T12:42:39+09:00
クラスとインスタンス
- 投稿日:2020-03-16T11:25:40+09:00
rspec-railsで使うコマンドを羅列する
- 投稿日:2020-03-16T11:20:30+09:00
gemとbundlerまとめ
- 投稿日:2020-03-16T01:34:36+09:00
Vultr VPSにCentOS8+MySQL8+nginx
はじめに
Vultrの一番安い10GB SSDプランだとCentOS8ではディスクが足りなくなるので25G以上をお勧めします。
MySQL 8 installation
$ sudo su Unistall MariaDB # yum -y remove mariadb-libs # rm -rf /var/lib/mysql/ Install MySQL 8 # yum -y install @mysql # systemctl start mysqld # systemctl enable --now mysqld # systemctl status mysqld# mysql_secure_installation Securing the MySQL server deployment. Connecting to MySQL using a blank password. VALIDATE PASSWORD COMPONENT can be used to test passwords and improve security. It checks the strength of password and allows the users to set only those passwords which are secure enough. Would you like to setup VALIDATE PASSWORD component? Press y|Y for Yes, any other key for No: y There are three levels of password validation policy: LOW Length >= 8 MEDIUM Length >= 8, numeric, mixed case, and special characters STRONG Length >= 8, numeric, mixed case, special characters and dictionary file Please enter 0 = LOW, 1 = MEDIUM and 2 = STRONG: 2 Please set the password for root here. New password: Re-enter new password: Estimated strength of the password: 100 Do you wish to continue with the password provided?(Press y|Y for Yes, any other key for No) : y By default, a MySQL installation has an anonymous user, allowing anyone to log into MySQL without having to have a user account created for them. This is intended only for testing, and to make the installation go a bit smoother. You should remove them before moving into a production environment. Remove anonymous users? (Press y|Y for Yes, any other key for No) : y Success. Normally, root should only be allowed to connect from 'localhost'. This ensures that someone cannot guess at the root password from the network. Disallow root login remotely? (Press y|Y for Yes, any other key for No) : y Success. By default, MySQL comes with a database named 'test' that anyone can access. This is also intended only for testing, and should be removed before moving into a production environment. Remove test database and access to it? (Press y|Y for Yes, any other key for No) : y - Dropping test database... Success. - Removing privileges on test database... Success. Reloading the privilege tables will ensure that all changes made so far will take effect immediately. Reload privilege tables now? (Press y|Y for Yes, any other key for No) : y Success. All done!Ruby V2.5.3 install
# yum -y install glibc-headers openssl-devel readline libyaml-devel readline-devel zlib zlib-devel bzip2 # yum install gcc-c++ # yum -y install git # cd /usr/local # git clone git://github.com/sstephenson/rbenv.git rbenv # git clone git://github.com/sstephenson/ruby-build.git rbenv/plugins/ruby-build # yum groupinstall "Development Tools" # yum install -y openssl-devel readline-devel zlib-devel # vi /etc/profile.d/rbenv.sh > 以下を記述してパスを通しておく。 export RBENV_ROOT="/usr/local/rbenv" export PATH="${RBENV_ROOT}/bin:${PATH}" eval "$(rbenv init --no-rehash -)" # source /etc/profile.d/rbenv.sh # rbenv install 2.5.3 <=これが時間がかかる。 # rbenv global 2.5.3 # rbenv rehashbundler 2.1.2 install
# gem install bundler -v 2.1.2node.js
# yum install -y nodejs # node --version v10.19.0yarn install
# npm install -g yarnNginx stable最新版をインストール
# yum install yum-utils/etc/yum.repos.d/nginx.repo[nginx-stable] name=nginx stable repo baseurl=http://nginx.org/packages/centos/$releasever/$basearch/ gpgcheck=1 enabled=1 gpgkey=https://nginx.org/keys/nginx_signing.key [nginx-mainline] name=nginx mainline repo baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/ gpgcheck=1 enabled=0 gpgkey=https://nginx.org/keys/nginx_signing.keyInstall
# cat /etc/redhat-release CentOS Linux release 8.1.1911 (Core) # yum --disablerepo=AppStream install -y nginx動作確認
nginx起動 # systemctl start nginx nginx自動起動設定 # systemctl enable nginx Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /usr/lib/systemd/system/nginx.service. 動作状態確認 # systemctl status nginx ● nginx.service - nginx - high performance web server Loaded: loaded (/usr/lib/systemd/system/nginx.service; disabled; vendor preset: disabled) Active: active (running) since Sun 2020-03-15 17:14:15 UTC; 5s ago Docs: http://nginx.org/en/docs/ Process: 3413 ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf (code=exited, status=0/SUCCESS) Main PID: 3414 (nginx) Tasks: 2 (limit: 5066) Memory: 2.0M CGroup: /system.slice/nginx.service ├─3414 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf └─3415 nginx: worker process Mar 15 17:14:14 vultrguest systemd[1]: Starting nginx - high performance web server... Mar 15 17:14:15 vultrguest systemd[1]: nginx.service: Can't open PID file /var/run/nginx.pid (yet?) after start: No such file or directory Mar 15 17:14:15 vultrguest systemd[1]: Started nginx - high performance web server.ブラウザでアクセス
snapshot
ここまででクリーンインストールが終わったので、他の作業前にスナップショットを取得しておく。
参考記事
How to Install MySQL 8.0 on CentOS 8 / RHEL 8
CentOSに最新版のGitをインストール・アップデートする方法
CentOS 8にNginx stable最新版をインストール(公式repository)
- 投稿日:2020-03-16T01:34:36+09:00
Vultr VPSにCentOS8+MySQL8+nginxをインストール
はじめに
CentOS7での記事の後、CentOS8も試したので、書き留めておきます。
Vultrの一番安い10GB SSDプランだとCentOS8ではディスクが足りなくなるので25G以上をお勧めします。以下の手順はRubyだけ古いバージョンですが、これはローカルのアプリが ruby 2.5.3 で動いているためです。2.7でも手順は同じでOKと思います。(未検証)
激安VPSのVultrで紹介者からのリンク経由でアカウント登録すると$100のクレジットをもらえるので、CentOS7, 8, MySQL 5.7, 8などの組み合わせをいろいろ試しました。このキャンペーンはいつ終わるか分からないので、興味のある方は以下のリンクからアカウント登録してください。あなたはクレジットをもらえるし、私にも多少のクレジットが入るらしいので、Win-Winです。
このリンクで$100もらえます
0. OS基本設定
前回のCentOS7での記事の1〜6までを行って、ユーザー作成やSwap領域の設定などをやっておきます。
1. MySQL 8 をインストール
$ sudo su Unistall MariaDB # yum -y remove mariadb-libs # rm -rf /var/lib/mysql/ Install MySQL 8 # yum -y install @mysql # systemctl start mysqld # systemctl enable --now mysqld # systemctl status mysqld# mysql_secure_installation Securing the MySQL server deployment. Connecting to MySQL using a blank password. VALIDATE PASSWORD COMPONENT can be used to test passwords and improve security. It checks the strength of password and allows the users to set only those passwords which are secure enough. Would you like to setup VALIDATE PASSWORD component? Press y|Y for Yes, any other key for No: y There are three levels of password validation policy: LOW Length >= 8 MEDIUM Length >= 8, numeric, mixed case, and special characters STRONG Length >= 8, numeric, mixed case, special characters and dictionary file Please enter 0 = LOW, 1 = MEDIUM and 2 = STRONG: 2 Please set the password for root here. New password: Re-enter new password: Estimated strength of the password: 100 Do you wish to continue with the password provided?(Press y|Y for Yes, any other key for No) : y By default, a MySQL installation has an anonymous user, allowing anyone to log into MySQL without having to have a user account created for them. This is intended only for testing, and to make the installation go a bit smoother. You should remove them before moving into a production environment. Remove anonymous users? (Press y|Y for Yes, any other key for No) : y Success. Normally, root should only be allowed to connect from 'localhost'. This ensures that someone cannot guess at the root password from the network. Disallow root login remotely? (Press y|Y for Yes, any other key for No) : y Success. By default, MySQL comes with a database named 'test' that anyone can access. This is also intended only for testing, and should be removed before moving into a production environment. Remove test database and access to it? (Press y|Y for Yes, any other key for No) : y - Dropping test database... Success. - Removing privileges on test database... Success. Reloading the privilege tables will ensure that all changes made so far will take effect immediately. Reload privilege tables now? (Press y|Y for Yes, any other key for No) : y Success. All done!2. Ruby V2.5.3 をインストール
# yum groupinstall "Development Tools" # yum -y install libyaml-devel # yum install -y openssl-devel readline-devel zlib-devel # cd /usr/local # git clone git://github.com/sstephenson/rbenv.git rbenv # git clone git://github.com/sstephenson/ruby-build.git rbenv/plugins/ruby-build # vi /etc/profile.d/rbenv.sh > 以下を記述してパスを通しておく。 export RBENV_ROOT="/usr/local/rbenv" export PATH="${RBENV_ROOT}/bin:${PATH}" eval "$(rbenv init --no-rehash -)" # source /etc/profile.d/rbenv.sh # rbenv install 2.5.3 <=これが時間がかかる。 # rbenv global 2.5.3 # rbenv rehash3. bundler 2.1.2 をインストール
自分の開発環境のBundlerが2.1.2なのでそれに合わせたが、バージョンは開発環境に合わせる。
# gem install bundler -v 2.1.24. node.js をインストール
# yum install -y nodejs # node --version v10.19.05. yarn をインストール
# npm install -g yarn6. Nginx stable最新版をインストール
(1)yum-utils をインストール
# yum install yum-utils/etc/yum.repos.d/nginx.repo[nginx-stable] name=nginx stable repo baseurl=http://nginx.org/packages/centos/$releasever/$basearch/ gpgcheck=1 enabled=1 gpgkey=https://nginx.org/keys/nginx_signing.key [nginx-mainline] name=nginx mainline repo baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/ gpgcheck=1 enabled=0 gpgkey=https://nginx.org/keys/nginx_signing.key(2) インストール
# cat /etc/redhat-release CentOS Linux release 8.1.1911 (Core) # yum --disablerepo=AppStream install -y nginx(3) 動作確認
nginx起動 # systemctl start nginx nginx自動起動設定 # systemctl enable nginx Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /usr/lib/systemd/system/nginx.service. 動作状態確認 # systemctl status nginx ● nginx.service - nginx - high performance web server Loaded: loaded (/usr/lib/systemd/system/nginx.service; disabled; vendor preset: disabled) Active: active (running) since Sun 2020-03-15 17:14:15 UTC; 5s ago Docs: http://nginx.org/en/docs/ Process: 3413 ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf (code=exited, status=0/SUCCESS) Main PID: 3414 (nginx) Tasks: 2 (limit: 5066) Memory: 2.0M CGroup: /system.slice/nginx.service ├─3414 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf └─3415 nginx: worker process Mar 15 17:14:14 vultrguest systemd[1]: Starting nginx - high performance web server... Mar 15 17:14:15 vultrguest systemd[1]: nginx.service: Can't open PID file /var/run/nginx.pid (yet?) after start: No such file or directory Mar 15 17:14:15 vultrguest systemd[1]: Started nginx - high performance web server.(4) ブラウザでアクセス
7. snapshot
ここまででクリーンインストールが終わったので、他の作業前にスナップショットを取得しておく。
8. Rails 6 をインストール
(1) Rails6のための事前準備
# yum install mysql-devel # gem install mysql2 -v '0.5.3' --source 'https://rubygems.org/' # gem install msgpack(2) Rails 6 をインストール
# gem install rails -v 6.0.2.1 ... Done installing documentation for concurrent-ruby, i18n, thread_safe, tzinfo, zeitwerk, activesupport, rack, rack-test, mini_portile2, nokogiri, crass, loofah, rails-html-sanitizer, rails-dom-testing, builder, erubi, actionview, actionpack, activemodel, activerecord, globalid, activejob, mini_mime, mail, actionmailer, nio4r, websocket-extensions, websocket-driver, actioncable, mimemagic, marcel, activestorage, actionmailbox, actiontext, thor, method_source, railties, sprockets, sprockets-rails, rails after 87 seconds 40 gems installed9. Test rails app
動作検証用に適当なアプリを作る。Capistranoでローカル環境からデプロイする場合はこの動作検証はスキップして構わない。
(1) directory preparation
$ sudo su [root@vultrguest var]# mkdir /var/www [root@vultrguest var]# mkdir /var/www/myapp [root@vultrguest var]# chown -R deploy.deploy /var/www(2) Gemfile preparation
$ bundle init Writing new Gemfile to /var/www/myapp/Gemfile $ vi Gemfile/var/www/myapp/Gemfile# frozen_string_literal: true source "https://rubygems.org" git_source(:github) {|repo_name| "https://github.com/#{repo_name}" } gem "rails" <= remove "#" here(3) rails new
$ bundle install --path vendor/bundle $ bundle exec rails new . -B -d mysql --skip-test $ bundle install --path vendor/bundle $ rails webpacker:install ... Webpacker successfully installed ? ? $ rails s => Booting Puma => Rails 6.0.2.1 application starting in development => Run `rails server --help` for more startup options Puma starting in single mode... * Version 4.3.3 (ruby 2.5.3-p105), codename: Mysterious Traveller * Min threads: 5, max threads: 5 * Environment: development * Listening on tcp://127.0.0.1:3000 * Listening on tcp://[::1]:3000 Use Ctrl-C to stop(4) telnetで確認
前提条件 :Port 3000が開いている事
$ yum list installed | grep telnet もしtelnetがインストールされていなければインストール $ sudo yum -y install telnet telnet-server$ telnet 127.0.0.1 3000 Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'. GET / HTTP/1.1 <=Enterを2回押す事。 HTTP/1.1 403 Forbidden Content-Type: text/html; charset=UTF-8 Content-Length: 3102 <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <title>Action Controller: Exception caught</title> <style> body { background-color: #FAFAFA; .... </body> </html> Connection closed by foreign host.これでPumaが動いていることは確認できました。外部からブラウザでアクセスするにはnginxとの連携の設定が必要です。
(5) Snapshot
一旦、ここまででスナップショットを取っておきます。
10. Capistrano3でデプロイ
今度はローカルの開発環境で作ったアプリをCapistrano3でデプロイしてみます。
前提条件
- GitHubにSSH公開鍵でローカルからPushできていること。
(1) Vultr VPSにアプリのデプロイ先ディレクトリを準備
$ sudo su # mkdir /var/www # mkdir /var/www/myapp # mkdir /var/www/myapp/shared # mkdir /var/www/myapp/shared/config # adduser www # chown -R www:www /var/www # chmod -R 770 /var/www/ # gpasswd -a deploy www # gpasswd -a nginx www(2) デプロイ対象外指定したファイルをコピー
$ scp -i ~/.ssh/vultr config/master.key deploy@SERVER_IP_ADDR:/var/www/myapp/shared/config/ $ scp -i ~/.ssh/vultr config/database.yml deploy@SERVER_IP_ADDR:/var/www/myapp/shared/config/(3) Capistrano関連Config
Gemfileに以下を追加# Use Capistrano for deployment group :development do gem 'capistrano' gem 'ed25519' gem 'bcrypt_pbkdf' gem 'capistrano-rbenv' gem 'capistrano-bundler' gem 'capistrano-rails' gem 'capistrano3-puma' endCapfile, config/deploy.rbを生成
ローカル環境のRails_rootで実行$ bundle exec cap install STAGES=productionCapfile, config/deploy.rbを設定
Capfileconfig/deploy.rb(4) nginx-puma連携
VPS事前準備
Vultrで作業# mkdir /etc/nginx/sites-available # mkdir /etc/nginx/sites-enabled # chgrp www sites-available # chgrp www sites-enabledcapistrano-pumaプラグインで設定ファイル自動生成
これらコマンドで、サーバ上の
/etc/nginx/sites-available
とshared/puma.rb
に設定ファイルが作られる。ローカル環境のRails_rootで実行$ bundle exec cap production puma:nginx_config 00:00 puma:nginx_config Uploading /tmp/nginx_myapp_production 100.0% 01 sudo mv /tmp/nginx_myapp_production /etc/nginx/sites-available/myapp_production ✔ 01 deploy@Vultr_IP_ADDR 0.200s 02 sudo ln -fs /etc/nginx/sites-available/myapp_production /etc/nginx/sites-enabled/myapp_production ✔ 02 deploy@Vultr_IP_ADDR 0.223s$ bundle exec cap production puma:config 00:00 puma:config Uploading /var/www/myapp/shared/puma.rb 100.0%デプロイ実行
ローカル環境のRails_rootで実行参考記事
How to Install MySQL 8.0 on CentOS 8 / RHEL 8
CentOSに最新版のGitをインストール・アップデートする方法
CentOS 8にNginx stable最新版をインストール(公式repository)
新規Railsプロジェクトの作成手順まとめ
- 投稿日:2020-03-16T00:16:26+09:00
Ruby, Rails たまに使うけどすぐ忘れるやつ
RailsとかRubyの過去に学んだものを適当に残しておく(最近はRailsもRubyも触ってない・・)
思い出したら随時追加する。rakeタスクをrails consoleから実行する
require 'rake' Rails.application.load_tasks Rake::Task['hoge:huga'].execute # 引数つけて実行 Rake::Task["hoge:huga"].execute({ hogege: 'hugaga' })bundle でバージョン指定してインストール
# bundle installするときはGemfile.lockのバージョンを確認してから実行 bundle _1.16.1_ installrakeタスク内のメソッドはObjectクラス直下に作られちゃう
https://blog.freedom-man.com/rake-definemethod-namespace
namespace配下にメソッド書いていると思っていてもObjectクラス以下に作られるのでバグの原因になるかもね
SQLをrails consoleから実行
sql="SELECT * from hoge);" result=ActiveRecord::Base.connection.select_all(sql).to_hashrspecの書き方で参考になるページ
http://www.betterspecs.org/jp/
ruby引数処理
わかりやすい記事
キーワード引数をhashとして受け取る方法とか
https://qiita.com/metheglin/items/306e81c95f8a5cdea296privateメソッドをrails consoleから呼び出す
# User.find_by(id: 1)は引数 # Hugaはクラス, hoge_private_methodはHugaクラス内のプライベートメソッド Huga.send(:hoge_private_method, User.find_by(id: 1) )CSV書き出し
使い捨てコード書くときによく使う
CSV.open('/tmp/hoge.csv','wb') do |csv| csv << [1,2] endテキスト読み込み
File.foreach("tmp/hoge.txt"){|f| s << f.chomp.to_i}rakeタスクの確認
bundle exec rake -vTrails consoleでexplainを実行
User.where(id: 1).joins(:articles).explainActiveSupportのString拡張(活用形)まとめ
https://qiita.com/hana-da/items/ec9ac3e1c8803f5fa1fc
"Invoice".tableize # => "invoices"メール送信
手元のメール送信確認はmailcacherを使ったことがある
https://qiita.com/pocari/items/de0436c39ffc65647cf0ActionMailer::Base.mail(to: "to@example.com", from: "from@example.jp", subject: "題名", body: "本文").deliver_nowメソッドの定義場所を探す
https://docs.ruby-lang.org/ja/latest/method/Method/i/source_location.html
Hoge.method(:huga).source_locationsqlファイルをrails dbに食わせる
bundle exec rails db < my_db.sql
日付と時刻を扱う
https://qiita.com/prgseek/items/c0fc2ffc8e1736348486
t = Time.parse("2017/04/25 19:23:55"); p t # 2017-04-25 19:23:55 +0900クエリ高速化
わかりやすい, Rails6はあまり知らない
https://texta.pixta.jp/entry/2016/02/10/180244
https://qiita.com/leon-joel/items/f26556c9e56833983856rails consoleの再読み込み
reload!
find_each
わかりやすかった
https://blog.toshimaru.net/rails-find_each/#order%E4%BB%98%E3%81%8D-find_eachスクリプト実行
Rails機能を使いつつ単独のスクリプトを実行する。
bundle exec rails runner hoge.rb 'huga'pry
わかりやすい
https://qiita.com/k0kubun/items/b118e9ccaef8707c4d9f
https://www.slideshare.net/cuzic/pry-repl
- 投稿日:2020-03-16T00:00:16+09:00
AtCoderの入力例を一度に試すための1行(Ruby)
AtCoder等のプログラミング問題を解く際、提出前に手元の環境で動作確認すると思う。私の場合は便利な環境を用意できていなく1、代わりに paiza.io を利用している2。
問題には入出力の例が複数与えられているのでなるべく全て試したいが、入力例をいちいち変えるのが辛い。自分で例を追加する場合は尚更である。
環境を整えてさえいれば、テストの自動生成なども可能なようだが…
何とかならないか考えた結果、Rubyにおいて1行で解決する方法を思いついた。
方法
Rubyスクリプトの最後に以下の1行を追加する。解答のメソッド化などは必要ない。
load __FILE__ unless $stdin.eof?あとは入力例を結合して読み込ませれば、全ての出力がまとめて表示される。
制限
解答のスクリプト内では「入力終端まで読み込む」ことをしてはいけない。問題に与えられた数字をもとに
#gets
などで正確な行数だけ取得しなければいけない。動作原理
単に同じスクリプトを何度も実行している。
Kernel.#load
はKernel.#require
と異なり、常に指定ファイルを読み込む。指定ファイルとして自分自身を与えれば、スクリプトを再び先頭から実行する効果が得られる。あとは無限ループ防止のために「入力終端でなければ」という条件を追加すればいい。例
AtCoder Beginner Contest 154 の A問題 に適用してみる。この問題は入力が3行で与えられる。
abc154_a.rbs, t = gets.split a, b = gets.split.map(&:to_i) u = gets.chomp if u == s a -= 1 else b -= 1 end puts "#{a} #{b}" load __FILE__ unless $stdin.eof?入力例が2つあるので、それらを結合して与える。
入力例1,2red blue 3 4 red red blue 5 5 blueすると、それぞれの結果がまとめて表示される。
出力2 4 5 4制限に違反した場合
解答のスクリプト内で「入力終端まで読み込む」ことをしてしまうと、一度に試すことはできなくなる。提出する分には問題ない。
abc154_a.rbs, t, *ab, u = $stdin.read.split ab.map!(&:to_i) ab[u == s ? 0 : 1] -= 1 puts ab * " " load __FILE__ unless $stdin.eof?出力3 3 0 0 0 5 5