- 投稿日:2021-01-22T23:49:37+09:00
投稿2日目
- 投稿日:2021-01-22T22:49:19+09:00
ExcelでCSV閲覧の際の0落ち問題
概要
WEBアプリケーションからダウンロードしたCSVをエクセルで開くと
0埋めしている社員番号から0が消えて表示される問題があったので、
対応内容をまとめました開発環境
- ruby 2.6.5
- Rails 5.1.7
まず、CSVを確認
出力されるCSVに問題はなく、0埋め済の社員番号が記載されていた。
sample.csvemployee_number,address 012345,tokyoエクセルで0落ちされないようCSVを加工
0落ち問題対応策の記事は多く、その1つは
CSVに変更を加える方法だった。
エクセルで文字列として表示できるよう、以下の記述に変更すれば
確かに0落ち問題が起きなかった。sample.csvemployee_number,address ="012345",tokyoでも、CSVはいじりたくない。
CSV出力は大量データを閲覧する目的もあるが、
そのCSVをアプリケーション側にインポートする目的もあった。
社員番号のようにDBではキーとなる値をいじりたくなかった。エクセルファイル出力機能をアプリケーションに追加
axlsx gemをインストール
インストール方法はgithubを参照
https://github.com/randym/axlsx各セルの表示形式を文字列に設定、エクセルファイルを出力
表示形式を指定しないと「標準」表示形式となり、
0落ち問題がおきるため、各セルの表示形式を
文字列として設定する必要がある。
- エクセルファイル出力の実装例
package = Axlsx::Package.new package.workbook.add_worksheet do |sheet| header = ['employee_number','address'] values = ['012345','tokyo'] sheet.add_row header # types オプションで各セルの表示形式指定ができる # https://github.com/randym/axlsx/blob/master/lib/axlsx/workbook/worksheet/worksheet.rb#L388 sheet.add_row values, types: Array.new(values.size, :string) end data = package.to_stream File.open('/tmp/zero_test.xlsx', 'w') do |file| file.write data.read end出力されたエクセルファイルを確認
出力されたファイルを開いてみると
社員番号が正しく表示された。
- 投稿日:2021-01-22T21:01:03+09:00
フレームワークとは
今回はフレームワークについて学習をしました。フレームワークとは何か、Ruby,PHP,JavaScript,CSSの代表的なフレームワークを公式サイトとURLと共に紹介します。
説明不足があると思いますので、気になったフレームワークを公式サイトで確認してみて下さい。フレームワークとは
「フレームワーク」という言葉には、「枠組み」という意味があり、アプリケーション開発においては、テンプレートの役割を持っています。テンプレートの機能は、開発を行う際に頻繁に必要とされる「基礎的な機能」をまとめて提供してくれるものです。
例えば、ログイン認証機能、新規投稿機能、検索機能などアプリケーション開発においてほとんど共通して使われる機能がパッケージ化されています。
そのため、フレームワークを用いることで開発を高速化させることが出来ます。
どれくらい便利なものかというと、ログイン認証を仮に自分で1から作成したとします。その場合、作らなければならないのが、ユーザーネーム、パスワードの欄を作り、それを認証、弾く機能、更にそれらを管理する画面など様々なところを作っていかなければなりません。しかし、フレームワークを使うことで、これらのベースとして使える骨組み部分がパッケージ化されているので、あとは自分好みに改良するだけで済みます。このパッケージのことをフレームワークと呼びます。もっと簡単に言えばコンピュータ言語を使用して何か開発したいと考えたとき、その手助けをしてくれる便利ツールの1つと考えておけば良いでしょう。
私がよくお世話になっているものだとRubyならRuby on Rails、CSSならBootstrapなどがあります。おすすめなフレームワーク
フレームワークには言語ごとにたくさんの種類があります。しかし、ここでは私が実際におすすめされた・よく聞くフレームワークを紹介していきます。
Rubyのオススメフレームワーク3種
- Ruby on Rails 公式サイト <https://rubyonrails.org/>
- Sinatra 公式サイト <http://sinatrarb.com/intro-ja.html>
- Padrino 公式サイト <http://padrinorb.com/>Ruby on Rails
「Rubyのフレームワークは?」と聞けば、ほとんど返ってくる答えが「Ruby on Rails」と言われるほど有名です。正直に言ってしまえば、Rubyでアプリ、システム開発を行いたいなら、Ruby on Railsを選択すれば間違いないでしょう。私自身一番最初に手をるけたのがRuby on Railsでした。また、素早くかつ効率的に開発するために、2つの大原則を設定しているのが特徴です。
それらの原則について私が紹介した記事がありますので、読んでみてください。
「DRY原則・CoC原則とは」
https://qiita.com/Shirosan10/items/84fe66955398e91f7136
このように徹底的に規約に従って行動することで、Webアプリ開発の高速化を目指します。Sinatra
Rubyで記述されているオープンソースのフレームワークになります。フレームワークの中では、最も少ないコードでWebアプリなどの開発が可能です。
そのため学習コストが少なくて済み、最も手軽にフレームワークを使用した開発を始めることができます。Padrino
先述の、Sinatraをベースに設計されたフレームワークになります。Sinatraにはなかった機能群があり、かつRuby on Railsよりも少ないコードでWebアプリ開発ができるので、初心者だけど、少々複雑なものを開発したい人向けです。
PHPのオススメフレームワーク3種
- Laravel 公式サイト <https://laravel.com/>
- CakePHP 公式サイト <https://cakephp.org/jp>
- FuelPHP 公式サイト <http://fuelphp.jp/>Laravel
数あるPHPのフレームワークで、Laravelは2011年に登場した最も若いフレームワークです。今現在注目度が高く、その理由は「Love beautiful code? We do too」という理念どおり、初心者であっても美しいコードを書ける点だと思います。コードが書きやすく、すぐに書き始めることができるので、PHPを習得した人が真っ先に使用できます。
CakePHP
PHPの中でも有名なフレームワークです。「ケーキを焼くように簡単に開発」を理念として開発されており、Ruby onRailsの影響も強く受けています。
特徴的なのは、MVC(モデル・ビュー・コントローラ)モデルと呼ばれる実装デザインに関する先駆けになったことです。
MVCモデルについて気になった方はこちらも読んでみてください。
拙いながらMVCについて図解を入れて解説しています。
「MVCモデルについて」
https://qiita.com/Shirosan10/items/d12416700f7e2329cb09FuelPHP
FuelPHPもLaravelと同じように、比較的最近登場したフレームワークです。そのため、ほかのPHPフレームワークの良いところ吸収しているので、使いやすいフレームワークです。
特徴としては、動作が軽量でフレームワークの規約が少ないため、自由にコードを記述出来ることが挙げられます。JavaScriptのオススメフレームワーク3種
- AngularJS 公式サイト <https://angularjs.org/>
- Vue.js 公式サイト <https://jp.vuejs.org/index.html>
- React 公式サイト <https://ja.reactjs.org/tutorial/tutorial.html>AngularJS
AngularJSはJavaScriptでできたWebフレームワークです。見た目の動きをきれいに作るために使用されます。
例えば、SPA(Single-page application)と呼ばれる、「ページを移動しなくてもなめらかにページ内のコンテンツが現れるような1ページで完結するアプリケーション」の開発を行う時などに採用されます。Vue.js
Vue.jsはAngularJSよりも後に開発されいます。そのため、他のフレームワークの良いところを組み込んだ設計になっています。
AngularJSよりも規約が少ないため、比較的自由にコードを記述出来、JavaScriptを学習したばかりの初心者におすすめされます。React
有名なSNS「Facebook」が中心となって開発したフレームワークです。React Nativeと呼ばれる、全く同じソースコードでiOSとAndoroidアプリ両方を動作させることが可能なため、モバイルアプリ開発に適しています。
CSSのオススメフレームワーク
Bootstrap 公式サイト <https://getbootstrap.com/>
Bootstrapは「Webデザインフレームワーク」と呼ばれ、CSS/JavaScriptから構成されています。Twitter社より提供されるフレームワークになるため、Twitterのようなフラットなデザインを簡単に作成することができます。クラスを指定するだけで簡単にレスポンシブデザインに対応したページを作ることが出来ます。
今回の記事は以上になります。
色々と拙い部分があるかと思います。
また、自分が実際に使っておらず調べたり、教科書に書いて有りそうな説明なってしまったものもあり、説明が淡々としすぎてしまいました。今後、自分で使いたいなと思ってメモしていたので理解が深まったら更新して行こうと思います。
間違っている点、理解が不完全な点があればご指摘いただければ幸いです。
- 投稿日:2021-01-22T20:50:09+09:00
続きを読む(truncate)の実装
環境
・rails 5.2.4
続きを読むの実装
snsでよくある続きを読むの実装の紹介をさせて頂きます。。
とっても簡単で以下のように末尾にtruncateと書くだけです。
images/index.html.erb<%= image.introduction.truncate(20) %>20文字以上で...で表示されるという意味です。
ちなみに、続きを読むのリンクは以下の記述で実装できました。
images/index.html.erb<%= image.body.truncate(20) %> <% if image.body.size >= 20 %> <%= link_to image_path(image.id) do %> <p>続きを読む</p> <% end %> <% end %>20文字以上だと続きを読むが表示されるというif文です。
簡単ですが、説明は以上となります。
ありがとうございました。
- 投稿日:2021-01-22T18:52:22+09:00
DRY原則とは
DRY(ドライ)原則について学習したので復習をかねてアウトプットします。
DRY原則とは
Don't Repeat Yourselfの略で、「繰り返しを避けるという意味合いがあります。
つまり、別々の場所で同じものを書いてはいけないよと言うことです。
なぜならば、コーディングをする上で同じコードを複数の場所に書くことは、その分だけ管理する場所がどんどん増えていくことを意味し、それだけ手間や時間が削られて行くからです。
はじめは数箇所だけだったとしても作業を重ねていくうちに増え、100箇所分すべて修正する事になった場合はどうでしょうか。
一箇所の修正だけならば早く解決できます。手作業の修正ならばなおさらバグや変更が減り、作業効率を向上してくれるでしょう。
もちろん、必ずしなければいけないということではなく、今後仕事として依頼を受ける時に全部の箇所を覚えていくことは難しくできる限り修正箇所を増やさないためにも頭の片隅においておくといい考え方です。
今回の記事は以上になります。
色々と拙い部分があるかと思います。
間違っている点、理解が不完全な点があればご指摘いただければ幸いです。
- 投稿日:2021-01-22T18:52:22+09:00
DRY原則・CoC原則とは
DRY(ドライ)原則、CoC原則について学習したので復習をかねてアウトプットします。
DRY原則とは
Don't Repeat Yourselfの略で、「繰り返しを避けるという意味合いがあります。
つまり、別々の場所で同じものを書いてはいけないよと言うことです。
なぜならば、コーディングをする上で同じコードを複数の場所に書くことは、その分だけ管理する場所がどんどん増えていくことを意味し、それだけ手間や時間が削られて行くからです。
はじめは数箇所だけだったとしても作業を重ねていくうちに増え、100箇所分すべて修正する事になった場合はどうでしょうか。
一箇所の修正だけならば早く解決できます。手作業の修正ならばなおさらバグや変更が減り、作業効率を向上してくれるでしょう。
もちろん、必ずしなければいけないということではなく、今後仕事として依頼を受ける時に全部の箇所を覚えていくことは難しくできる限り修正箇所を増やさないためにも頭の片隅においておくといい考え方です。
CoC原則とは
Convention over Configurationの略で、「設定よりも規約を優先する」という考え方です。
どういうことかと言いますと、例えばRuby on Railsではファイル名の規約・テーブル定義の規約など様々な規約がありますがこの規約通りに記述することで、コードの量を大幅に減らすことが出来ます。
それと同時に考える時間も大幅に減らすことが出来るので、作業効率、開発速度が向上します。
例えば、アソシエーション(テーブル同士の関係性)を示すhas_manyやbelongs_toなどすでに決まっている単語があります。これらは関連付けをする時に覚えておかないと関連付けが出来ません。
もちろん自分で設定することが出来るものもありますが、その都度考え、設定していったのでは物凄く時間をかけてしまいます。
Ruby on Railsには他にもたくさんの規約に則した単語があります。その一つ一つに意味(役割)があると思って覚えていくのが良いでしょう。今回の記事は以上になります。色々と拙い部分があるかと思います。間違っている点、理解が不完全な点があればご指摘いただければ幸いです。
今回の記事は以上になります。
色々と拙い部分があるかと思います。
間違っている点、理解が不完全な点があればご指摘いただければ幸いです。
- 投稿日:2021-01-22T17:53:19+09:00
Rails gem 'devise'でログアウトをコントローラから一発で呼ぶ方法
- 投稿日:2021-01-22T17:41:34+09:00
BASIC認証とは
自分の備忘録用
Basic認証とは
ベーシック認証(Basic認証)とはWebサイトの特定の領域、つまりページやファイルにアクセス制限をかけることができる認証方法の1つ。ベーシック認証をかけると、認証をかけたWebサイトにアクセスしようとしたとき、下の画像のような認証ダイアログが立ち上がって、ユーザー名(ID)とパスワードの入力が求められる。
設定方法
まずトップページのコントローラーに before_action :basic_authを定義する。
「basic_auth」は変数名なので名前はこれじゃなくてもいい。
class アプリ名Controller < ActionController::Base before_action :basic_auth private def basic_auth authenticate_or_request_with_http_basic do |username, password| username == 'ユーザー名' && password == '好きなパスワード' end end endここに出てくる「authenticate_or_request_with_http_basic」と言うメソッドはRailsに用意されているメソッドで
Basic認証を使うときに必要、ブロックの中にusernameとpasswordを入れdo〜endの中にそれぞれ設定する保守性
でもこのままだとパスワードが丸見えになるので環境変数を設定しその中にusernameとpasswordを代入する形を取る。
macOSがCatalina以降なら
俺はCatalinaなのでこっち% vim ~/.zshrc # .zshrcを開いたら、「i」とタイプしてインサートモードに移行 # .zshrcの内部に次の記述を追加 export BASIC_AUTH_USER='ユーザー名' export BASIC_AUTH_PASSWORD='好きなパスワード' # 記述を追加したら、escキーを押してインサートモードを抜け、 「:wq」と入力して保存して終了する # .zshrcを再読み込みし、定義した環境変数を有効にする % source ~/.zshrcmacOSがMojave以前なら
$ vim ~/.bash_profile # .bash_profileを開いたら、「i」とタイプしてインサートモードに移行 # .bash_profileの内部に次の記述を追加 export BASIC_AUTH_USER='ユーザー名' export BASIC_AUTH_PASSWORD='好きなパスワード' # 記述を追加したら、escキーを押してインサートモードを抜け、 「:wq」と入力して保存して終了する # .bash_profileを再読み込みし、定義した環境変数を有効にする $ source ~/.bash_profile設定できたらコントローラーに戻って以下に編集
def basic_auth authenticate_or_request_with_http_basic do |username, password| username == ENV["BASIC_AUTH_USER"] && password == ENV["BASIC_AUTH_PASSWORD"] # 環境変数を読み込む記述に変更 end endheroku上にも環境変数を反映させるには
% heroku config:set BASIC_AUTH_USER="ユーザー名" % heroku config:set BASIC_AUTH_PASSWORD="好きなパスワード"
設定できたかを確かめるコマンド⬇︎
% heroku config設定したらデプロイを忘れない
% git add . % git commit -m "Basic認証を導入" % git push heroku master
できたぁ!(悟空)
- 投稿日:2021-01-22T16:45:57+09:00
refileの画像保存先を変更した際のこと
画像のアップロードにrefileを使用していて、ファイルの保存先を変更することがあったので備忘録として書きます。
開発環境
- Ruby 2.6.3
- RubyOnRails 5.3.4
Gemfile.# 画像アップロードにrefileを利用 gem "refile", require: "refile/rails", github: 'manfe/refile' gem "refile-mini_magick"保存先の変更
デフォルトだとアップロードされた画像は tmp/uploads/store に保存されます。
今回は public/uploads/ に変更したかったので、configのinitializers配下にrefile.rbというファイルを作成し、下記のように設定を加えます。config/initializers/refile.rbRefile.backends['store'] = Refile::Backend::FileSystem.new('public/uploads/')これで、保存先を変更することができました。
しかし、本番環境を確認すると困ったことが起きました。
画像ファイルを読み込む場所を変更したので、当然のことですが、
変更前にアップロードした画像が表示されなくなってしまいました。試しに変更前にtmp配下に保存されたファイルたちをpublicに移動してあげたら無事表示されました。
terminal.$ cp tmp/uploads/store/* public/uploads/どのケースでもこの対応で解決できるかはわかりませんが、どなたかの参考になれば幸いです。
- 投稿日:2021-01-22T16:30:09+09:00
Ruby初心者向けプログラミング問題10選を解いてみた(上)
何か投稿してみようということで、少し前に解いた練習問題を貼っていきたいと思います
高度なテクニックは全く使っていないので、初心者の方も安心してご覧くださいコード、本文ともに見づらいと思いますがご勘弁を…
素晴らしき元サイト様
アウトプットのネタに困ったらこれ!?Ruby初心者向けのプログラミング問題を集めてみた(全10問)
カレンダー作成問題
問題文
問題文(折りたたみ)
Date クラスを使って、今月の1日と月末の日付と曜日を求め、次のような形式でカレンダーを表示させてください
April 2013 Su Mo Tu We Th Fr Sa 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 3コード
require "date" today = Date.today first_date = Date.parse(today.strftime("%Y.%m.1")) last_date = (first_date >> 1) - 1 puts today.strftime("%B %Y").center(21) puts " Su Mo Tu We Th Fr Sa" print " " * first_day.wday (1..last_day.day).each do |day| print day.to_s.rjust(3) print "\n" if (first_date.wday + day) % 7 == 0 || day == last_day.day end要点解説
today = Date.today first_date = Date.parse(today.strftime("%Y.%m.1")) last_date = (first_date >> 1) - 1今日、月初、月末のDateオブジェクトを定義します
月初は、
today
をフォーマットし、その月の一日の文字列を作ってparse
しています
月末は来月のfirst_date
の1日前として今月の最終日を求めていますprint " " * first_day.wday
wday
で得られる値は、0から始まる曜日を表す数字です (日曜→0, 月曜→1・・・という感じ)
その回数空白を出力すれば、1日までの空白を再現できますprint "\n" if (first_date.wday + day) % 7 == 0 || day == last_day.day1日の位置+現在の日付が7の倍数になったら改行します
カラオケマシン問題
問題文
問題文(折りたたみ)
かえるのうたのメロディは以下のような文字列で表現されます。
"C D E F |E D C |E F G A |G F E |C C |C C |CCDDEEFF|E D C "
縦棒( | )は小節の区切りです。
半角スペースは休符です。
音符と休符が8つ集まると1小節になります。このメロディ(文字列)を変更するKaraokeMachineというクラスを作ります。
このクラスはインスタンス作成時にメロディを受け取ります。
transposeというメソッドに変化させたいキーの量を渡すと、その分だけキーを上げたり下げたりしたメロディが返却されます。
コード
class KaraokeMachine SCALE = %w(C C# D D# E F F# G G# A A# B).freeze def initialize(melody) @melody = melody end def transpose(amount) @melody.gsub(/[A-G]#?/) { |sub| SCALE[(SCALE.index(sub) + amount) % 12] } end end要点解説
@melody.gsub(/[A-G]#?/) { |sub| SCALE[(SCALE.index(sub) + amount) % 12] }正規表現での置換を使います
まず「A-Gのいずれかと#が0か1個ある」文字列をブロックに渡します
ブロック内部ではSCALE
の(SCALE.index(sub) + amount) % 12
の音階を返します試しに書いてみたら何故か通ってしまったコードなので、
(SCALE.index(sub) + amount) % 12
が上手くいく理由は全くわかりません()ビンゴカード作成問題
問題文
問題文(折りたたみ)
1から75までの数字をランダムに配置して、ビンゴカードを作成するプログラミング問題です。
ただし、実際のビンゴカードのルールに沿って、各列は以下のような仕様で数字を出力する必要があります。
- B:1~15のどれか
- I:16~30のどれか
- N:31~45のどれか
- G:46~60のどれか
- O:61~75のどれか
出力例は以下のとおりです。
B | I | N | G | O 13 | 22 | 32 | 48 | 61 3 | 23 | 43 | 53 | 63 4 | 19 | | 60 | 65 12 | 16 | 44 | 50 | 75 2 | 28 | 33 | 56 | 68
ビンゴカードを文字列として出力する、Bingo.generate_card メソッドを作成してください。
(中略)
Bingo.generate_card メソッドの出力結果は上で述べた数字のルールのほかに、以下の仕様を満たす必要があります。毎回異なるカードを生成します。
各列はパイプ(|)で区切ります。
数字や"BINGO"の文字は右寄せで出力します。
真ん中(FREEになる場所)はスペースを出力します。
コード
(ウンコードです)
class Bingo def self.generate_card %w(B I N G O).each_with_index do |chr, i| column = ["#{chr}"] iex = (i + 1) * 15 5.times do |c| column << rand((iex + 1 - 15)..iex).to_s redo if column.uniq! if chr == "N" && c == 2 column.pop column << " " end end instance_variable_set("@#{chr}", column) end @B.zip(@I, @N, @G, @O) do |row| puts row.map { |x| x.rjust(2) }.join(" | ") end end end要点解説
5.times do |c| column << rand((iex + 1 - 15)..iex).to_s redo if column.uniq! if chr == "N" && c == 2 column.pop column << " " end endB,I,N,G,Oの文字列の入ったそれぞれの配列にランダムな数字を入れていきます
(iex + 1 - 15)..iex
はごちゃごちゃしてますが、一応期待通りの範囲オブジェクトを作れます
uniq!
は重複する値が無いとnil
を返します
なので、if文の条件式にするとuniq!
が適用されcolumn
から重複した値が除かれた場合にredo
しますinstance_variable_set("@#{chr}", column)第1引数を変数名、第2引数を中身としてインスタンス変数を定義できるメソッドです
苦肉の策です…ボーナスドリンク問題
問題文
問題文(折りたたみ)
ある駄菓子屋で飲み物を買うと、空き瓶3本で新しい飲み物を1本プレゼントしてくれる。
最初に購入した飲み物の本数から、トータルで飲める本数を算出するプログラムを作成せよ。
また、最初に100本購入した場合、トータルで何本飲めるか。
*新しい飲み物が3本揃えばまた一本貰えるというひっかけ問題(?)
コード
def bounus_drink(amount) all_ju = [amount] dividend = amount loop do result = dividend.divmod(3) all_ju << result[0] dividend = result.sum break if dividend < 3 end all_ju.sum end要点解説
loop do result = dividend.divmod(3) all_ju << result[0] dividend = result.sum break if dividend < 3 end交換できた本数(
dividend / 3
の商)と、交換で手に入れた新しい飲み物も含めた交換できてない本数(dividend /3
の余り)の合計が3以下になるまで3で割り続けます
再帰処理?ナニソレオイシイノ?電話帳作成問題
問題文
問題文(折りたたみ)
カタカナ文字列の配列を渡すと、ア段の音別にグループ分けした配列を返すプログラムを作成する問題です。
# INPUT ['キシモト', 'イトウ', 'ババ', 'カネダ', 'ワダ', 'ハマダ'] # OUTPUT [ ['ア', ['イトウ']], ['カ', ['カネダ', 'キシモト']], ['ハ', ['ハマダ', 'ババ']], ['ワ', ['ワダ']] ]コード
class NameIndex KATAKANAS =[ ('ア'..'オ').to_a << 'ヴ', ('カ'..'ゴ').to_a, ('サ'..'ゾ').to_a, ('タ'..'ド').to_a, ('ナ'..'ノ').to_a, ('ハ'..'ボ').to_a, ('マ'..'モ').to_a, ('ヤ'..'ヨ').to_a, ('ラ'..'ロ').to_a, ('ワ'..'ン').to_a ].freeze def self.create_index(names) name_index = [] KATAKANAS.each do |katakana| matched = names.select { |name| katakana.include?(name.chr) } name_index << [katakana[0], matched.sort] unless matched == [] end name_index end end要点解説
matched = names.select { |name| katakana.include?(name.chr) }
names
から1文字目がkatakana
に含まれいるものを抜き出します
問題文の例でいうと、katakana
が('ア'..'オ').to_a << 'ヴ'
だった場合、matched
は["イトウ"]
になりますつづく
以上、前半の5問でした
(下)はまた後日
- 投稿日:2021-01-22T16:19:22+09:00
gem wheneverをdockerで使う
環境
Docker Engine 20.10.2
Ruby 2.7.0
Bundler 2.1.4手順
wheneverをGemfileへ
# Gemfile source 'https://rubygems.org' git_source(:github) do |repo| "https://github.com/#{repo}.git" end gem 'whenever'コンテナにcronをインストール
# Dockerfile FROM ruby:2.7.0 RUN apt-get update && apt-get install -y cron && apt-get install -y vim WORKDIR /usr/src/app COPY Gemfile . COPY Gemfile.lock . RUN bundle installコンテナのsetupとwheneverの設定
$ docker build -t test_image . $ docker create --name="test_container" -it -v "$PWD":/var/src/app test_image $ docker start test_container $ docker exec -it test_container /bin/bash /usr/src/app# bundle exec wheneverize .以下の設定ファイルができるのでカスタマイズする
# schedule.rb # # Use this file to easily define all of your cron jobs. # # It's helpful, but not entirely necessary to understand cron before proceeding. # http://en.wikipedia.org/wiki/Cron # Example: # set :output, "log/cron_log.log" # every 1.hours do # command end # # every 4.days do # runner "AnotherModel.prune_old_records" # end # Learn more: http://github.com/javan/wheneverもう一度コンテナに入りコマンドを実行
$ docker exec -it test_container /bin/bash /usr/src/app# bundle exec whenever # => # 0 0,2,4,6,8,10,12,14,16,18,20,22 * * * /bin/bash -l -c '/usr/bin/some_great_command >> /path/to/my/cron_log.log 2>&1' # 0 0,2,4,6,8,10,12,14,16,18,20,22 * * * /bin/bash -l -c 'cd /usr/src/app && bundle exec script/runner -e production '\''MyModel.some_method'\'' >> /path/to/my/cron_log.log 2>&1' # 0 0,2,4,6,8,10,12,14,16,18,20,22 * * * /bin/bash -l -c 'cd /usr/src/app && RAILS_ENV=production bundle exec rake some:great:rake:task --silent >> /path/to/my/cron_log.log 2>&1' # 0 0 1,5,9,13,17,21,25,29 * * /bin/bash -l -c 'cd /usr/src/app && bundle exec script/runner -e production '\''AnotherModel.prune_old_records'\'' >> /path/to/my/cron_log.log 2>&1'cronを起動
/usr/src/app# service cron start #=> [ ok ] Starting periodic command scheduler: cron.
cronが動いているか確認
/usr/src/app# service cron status #=> [ ok ] cron is running.
参考
- 投稿日:2021-01-22T14:48:04+09:00
【Rails】seedとFakerでランダムなサンプルデータを作成
はじめに
データベースに予め大量のデータを入れておきたいとき手動では大変です。
この記事ではseedとFakerを使って、自動でランダムなサンプルデータを作成する方法を紹介します。seedについて
seedファイルは、データベースにあらかじめ入れておきたいデータを定義しておくものです。
データをあらかじめ定義しrails db:migrate
することで、簡単にDBへデータを投入できます。gem 'faker'について
Fakerとはランダムな値を入れられるgemです。
Gemfileの中にgem 'faker'を追記し、 bundle installコマンドを実行することで使用出来る様になります。詳しくは下記の公式ページを参照してください。
【公式】
https://github.com/faker-ruby/faker開発環境
ruby 2.6.5
Rails 6.0.3.4
faker 2.15.1
gimei 0.5.1fakerインストール
Gimilegem 'faker' gem 'gimei'
gimei
は、日本人の名前や、日本の住所をランダムに返すGemです。ターミナルbundle install今回demosデーブルに200件のダミーデータを追加します。
db/seeds.rbrequire 'faker' 200.times do |n| sample_name = Gimei.kanji sample_kana = Gimei.katakana sample_email = Faker::Internet.email sample_tel = Faker::Number.number(digits: 11) start_time = Faker::Date.forward(50) # start_time = Faker::Date.between(from: '2021-01-01', to: '2021-04-30') #期間を限定することもできます。 Demo.create!( sample_name: sample_name, sample_kana: sample_kana, sample_email: sample_email, sample_tel: sample_tel, sample_product_name: "京都ツアー", price: "19600", num_id: "2", start_time: start_time, sample_id: "1", created_at: "2021-01-01 00:00:00", updated_at: "2021-01-01 00:00:00" ) endターミナルrails db:seedまとめ
fakerの使い方さえわかれば非常に簡単です。
このデータを検索機能のサンプルにするのも良いと思います。最後に
同じ様に悩んでる方々の助けになればと思い、記事を投稿しております。
それでは、また次回お会いしましょう〜参考
- 投稿日:2021-01-22T14:18:14+09:00
パッケージ mysql-server は利用できません。 というエラーについて
こんにちは!
独学でRailsアプリを作成し、AWS EC2上に手動でデプロイしたとき想像以上に大変だったので、出会った主なエラーとその解決方法を複数の記事に分けて記します。同じ様にエラーで悩んでいる方にとって参考になれば幸いです。環境
ローカル環境
・Ruby 2.7.2
・Ruby on Rails 6.0.3
・MySQL 8.0.2
EC2上の環境
・OS:Amazon Linux 2今回はこの記事を参考にデプロイしました。
https://hackmd.io/4_1NYUTBSaSsOC8cur7WhA?view事象
EC2インスタンスにSSH通信でログインし以下のコマンドでパッケージをインストールしました。
$ sudo yum -y install git make gcc-c++ patch openssl-devel libyaml-devel libffi-devel libicu-devel libxml2 libxslt libxml2-devel libxslt-devel zlib-devel readline-devel mysql mysql-server mysql-devel ImageMagick ImageMagick-devel epel-release sqlite sqlite-develパッケージのインストールが進んでいく中ログの中に気になるメッセージがありました。
パッケージ mysql-server は利用できません。どういうことでしょうか。このままではMySQLを使うことができないことは自分でも理解できました。
解決方法
原因を突き止めるべく調べてみると、どうやらEC2インスタンスにはデフォルトでMariaDBが入っており、それと競合することからこのメッセージが出たということがわかりました。
つまり、MariaDBを削除すればMySQLがインストールできるのではないかと考え、以下のコマンドを実行しました。$ sudo yum remove mariadb-libs $ rm -rf /var/lib/mysql/ $ sudo yum localinstall http://dev.mysql.com/get/mysql57-community-release-el7-7.noarch.rpm $ sudo yum -y install mysql-community-server手順としては以下の通りです。
①MariaDBライブラリ
②データフォルダの削除
③MySQL公式のyumリポジトリの追加
④MySQLのインストールそしてバージョン確認のコマンドを実行して、正常に出力されれば成功です。
$ mysqld --version最後までお読みいただきありがとうございました。
参考
https://weblabo.oscasierra.net/installing-mysql57-centos7-yum/
https://qiita.com/riekure/items/d667c707e8ca496f88e6
- 投稿日:2021-01-22T13:19:07+09:00
RubyとHTMLにおけるクラス名の書き方の違い
クラス名の付け方の違い
1.HTMLでのクラス名の付け方は、このようにclass="#"として名付けることができます。
<a href="##", class="#"> 〇〇 </a>2.Rubyでのクラス名の付け方は、class:"#"として名付けることができます。
<link_to "##",class:"#">最後に
私の学習順序ではHTMLが先だったのでclassの記述の仕方についてはclass="#"でしかないと思っていましたが、rubyの記述で同じ記述をした場合rubyにおけるクラスとインスタンスの方のclassが与えられてしまっていたので、ここは覚えておかなければいけないポイントなのではないかと思い、記事を書かせていただきました。このほかにも上記のようなlink_toの書き方であったり、form_withなどはHTMLと書き方が違うのでまた必要だと思ったことは書かせていただきます!!
- 投稿日:2021-01-22T13:15:33+09:00
mapメソッドの実践的な使い方
課題
皆さんは、ポートフォリオ等でオリジナルアプリを作成する際に下記のようなことで困ったことはありませんか?
- マイページで口コミを投稿した店舗(商品)を一覧で表示したいが、店舗(商品)を取得する方法がわからない。
イメージとしては以下のような感じです。※paramsではユーザーidのみ取得可能
histories_controller.rbdef index user = User.find(params[:user_id]) @reviews = Review.where(user_id: user.id) endここから、ビューファイルに店舗一覧を表示したいと思うと以下のように無理やりになってしまいます。
※一部抜粋views/histories/index.html.erb<% @reviews.each do |review| %> 店舗名:<%= review.shop.name%> 店舗投稿された口コミ数:<%= review.shop.reviews.count%> 口コミの全内容:<% review.shop.reviews.each do |review|%> 口コミのタイトル<%= review.title%> 口コミ投稿者<%= "by #{review.user.name}"%> <% end %> <% end %>これ見づらいだけでなく、同じ店舗に口コミを2回している場合、一覧でも店舗が2回登場してしまいます。
どうにかして、特定のユーザーのマイページでそのユーザーが口コミを投稿した店舗を取得したい、、
しかし、reviews変数が配列で要素を所持しているから扱いづらい、、結論
その時にmapメソッドが非常に役に立ちます!
結論から言うと下記の書き方で口コミした店舗データのみを取得できます。histories_controller.rbdef index user = User.find(params[:user_id]) reviews = Review.where(user_id: user.id) @shops = Shop.where(id: reviews.map{|review| review.shop_id}) endmapメソッドは公式リファレンスによると以下の説明が書いています。
各要素を順番にブロックに渡して評価し、その結果で要素を置き換えます。
つまり、reviews変数がもつ配列内のすべての要素に対して、whereメソッドで検索したことになります。
reviews内の各要素を順番にreview変数にいれた後にshop_idを参照しているということです。これで、口コミしたことがある店舗データをshops変数内に取得しました。
しかもwhereメソッドにはdistinctの処理が自動的に入っているので、店舗データの重複はしないようになっています。その結果ビューファイルも以下のようにスッキリ記載することができます。
views/histories/index.html.erb<% @shops.each do |shop| %> 店舗名:<%= shop.name%> 店舗投稿された口コミ数:<%= shop.reviews.count%> 口コミの全内容:<% shop.reviews.each do |review|%> 口コミのタイトル<%= review.title%> 口コミ投稿者<%= "by #{review.user.name}"%> <% end %> <% end %>こんな感じでスッキリしました!
Arrayクラスを扱うときはmapメソッド、めちゃくちゃおすすめなので、ぜひ使ってみてください。
- 投稿日:2021-01-22T13:04:38+09:00
単体テストエラー 〜ActiveRecord::StatementInvalid: Mysql2::Error::ConnectionError: Lost connection to MySQL server during query〜
自分の備忘録として残しておきます
エラー内容
ActiveRecord::StatementInvalid:
Mysql2::Error::ConnectionError: Lost connection to MySQL server during queryスクショを見る限り一つ目のテストは成功してるのに二つ目以降のテストは失敗している、、、なぜ?
可能性としてはテストに負荷がかかりすぎてread_timeout以内に処理が終わらなかった。spec/models/ファイル名_spec.rbRSpec.describe UserAddress, type: :model do before do @user = FactoryBot.create(:user) @item = FactoryBot.create(:item) @user_address = FactoryBot.build(:user_address, user_id: @user.id, item_id: @item.id) sleep 0.1 #この1行を追加 end #以下略sleep 0.1上記の記述はインスタンスを生成する処理に0.1秒待機させてread_timeoutのエラーを回避するための記述です。
できたぁ!(悟空)
- 投稿日:2021-01-22T12:24:31+09:00
単体テストのエラー 〜ActiveRecord::RecordInvalid: Validation failed: Email has already been taken〜
単体テストして変なエラーが出たので備忘録として残しておきます
結論
「そのメールは既に登録されているよ」って怒られてます。
この時僕はFakerでメールを作らずに手入力で入れていてのでテスト内でuserが何度も作成されるにあたって手動で入れてしまうとメールが重複してしまった、と言うことになります
以下コード
fuctories/user.rbFactoryBot.define do factory :user do nickname {"tarou"} email {"sanple.sample@com"} #emailを以下に変更⬇︎ email {Faker::Internet.free_email} #emailを上記に変更⬆︎ password {"a1234567"} password_confirmation {"a1234567"} last_name {"山田"} last_name_kana {"ヤマダ"} first_name {"太郎"} first_name_kana {"タロウ"} birthday {"2000-01-01"} end end
- 投稿日:2021-01-22T09:31:58+09:00
Ruby on Rails6でのjQueryの実装方法(Windows10 + 仮想環境)
Rails5までの実装方法を試してみてもjQueryが動かなかったので調べてみると、
Railsのversionが上がり、Rails6になってからはjQueryの実装方法が変わったようなので、
自分の勉強もかねて、読んでくださる方々に共有させていただきます。※プログラミング初心者ですので、おかしい点などがありましたら指摘してもらえると助かります。
開発環境
- 使用PC:Windows10
- 仮想環境:vagrant + CentOS7
- テキストエディタ:VSCode
- Ruby version:ruby2.5.8
- Rails version:6.1.1
実装したい環境
Ruby on Rails6での環境でjQueryを実装したい
目次
- jQueryインストール
- application.jsのファイル先の変更
- Webpackの設定
- application.jsの設定
- 外部ファイル作成
1. jQueryインストール
Rails5までのverでは、GemfileにjQueryを記載して
bundle install
していた。しかし、Rails6ではWebpacketを利用してjQueryをインストールします。【Windowsの人はこちらのコマンド yarnが使えない人用】
npm add jquery
【Macの人はこちらのコマンド yarnが使える人用】
yarn add jquery
2. application.jsのファイル先の変更
Rails5ではapplication.jsファイルは
【Rails5の場合】
app/assets/javascript/application.jsにあった。しかしRails6では
【Rails6の場合】
app/javascript/packs/application.jsファイルの場所が変わっている。
application.jsの head 内に以下のコードが追記されているか確認する。
追記されていない場合は追記する。app/javascript/packs/application.js<head> // ~他のコードが記載されている <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %> // ↑のコードが記載されているか </head>3. Webpackの設定
Webpackの設定に以下を追記する。
config/webpack/environment.js に追記する
config/webpack/environment.jsconst { environment } = require('@rails/webpacker') // 以下を追記 const webpack = require('webpack') environment.plugins.prepend('Provide', new webpack.ProvidePlugin({ $: 'jquery/src/jquery', jQuery: 'jquery/src/jquery' }) ) // ここまで module.exports = environment4. application.jsの設定
【Rails6の場合】
app/javascript/packs/application.jsrequire("@rails/ujs").start() require("turbolinks").start() require("@rails/activestorage").start() require("channels") require ('test.js') //追加 自分が決めたjsのファイル名【Rails5の場合】
app/assets/javascript/application.jsimport Rails from "@rails/ujs" import Turbolinks from "turbolinks" import * as ActiveStorage from "@rails/activestorage" import "channels" Rails.start() Turbolinks.start() ActiveStorage.start()僕はRailsのバージョンが違うと何が変更されるのかなど、よくわかっておらず、Rails5のapplication.jsのコードの下や上にRails6のコードを書いたりしててjQueryが動かなかったので注意が必要かもです。
5. 外部ファイル作成
次に外部ファイルにjQueryコードを書いていく。
今回は例としてtest.jsとファイル名をする。
ファイルは app/javascript/ このjavascriptフォルダより下に格納する。※フォルダを新たに作って、その下に格納してもいい。
app/javascript/test.js$(function() { $(".title").css("color", "red"); });今回は例として post/index.html.erb にjQueryを実行してみる。
viewやコントローラーやモデルなどはすでに作られている前提で書いていきます。app/views/posts/index.html.erb<title>Hello World</title>実際に
rails s
して確認してみる。正常に動きました。
4. でapplication.js に require ('test.js') を追加したので
どのViewファイルでも test.js(好きなファイル名) に書き込めばjQueryが実行される。app/views/posts/index.html.erb に直接jQueryを書き込むこともできるが、
重くなったり、管理がしづらかったりなど、あまり使われていないです。app/views/posts/index.html.erb<title>Hello World</title> <script> $(".title").css("color", "blue"); </script>最後まで見てくれてありがとうございます。
プログラミングの勉強一緒に頑張りましょう!
- 投稿日:2021-01-22T09:29:10+09:00
bundleやgemが遅いと思ったらIPv6を切っていたからだった
TL;DR
bundleが遅いと思ったらIPv6が切れていた。
環境
Zorin OS 15.3 (Ubuntu 18.04相当)
> bundle install Fetching gem metadata from https://rubygems.org/. Retrying dependency api due to error (2/4): Bundler::HTTPError Network error while fetching https://index.rubygems.org/api/v1/dependencies?gems=twitter-text-simpleidn (execution expired) Retrying dependency api due to error (3/4): Bundler::HTTPError Network error while fetching https://index.rubygems.org/api/v1/dependencies?gems=twitter-text-simpleidn (execution expired) Retrying dependency api due to error (4/4): Bundler::HTTPError Network error while fetching https://index.rubygems.org/api/v1/dependencies?gems=twitter-text-simpleidn (execution expired) Network error while fetching https://rubygems.org/quick/Marshal.4.8/twitter-text-simpleidn-3.0.0.0.gemspec.rz (execution expired)Bundleがよく失敗するし遅い!
原因
IPv6が切れてました。
自宅のネットワークの IPv4 over IPv6 が有効になっていたのが原因かもしれません。
解決方法
IPv6をオンにする。
参考資料
以下の例では逆にIPv6を切ることで解決している。
- 投稿日:2021-01-22T09:10:45+09:00
RubyGems の作成・公開手順【Ruby 2.6】
今回 RubyGems にライブラリを公開しました。その作成・公開の手順をまとめます。
環境
- Ruby 2.6.4
- Bundler 2.2.6
手順
大まかな流れは「【Ruby】gemの作り方から公開まで 」を参考にさせていただきました。こちらで非常に良くまとめられているので、以下では手順をザッと列挙していきます。
作成
プロジェクトの準備
bundler の更新後、次のコマンドで gem の雛形を作成します。
bundle gem [YOUR_GEM_NAME] -t自動生成のために設定を色々と聞かれます。
Test framework
Do you want to generate tests with your gem? . . . Enter a test framework. rspec/minitest/test-unit/(none): rspecCI service
Do you want to set up continuous integration for your gem? Supported services: . . . Enter a CI service. github/travis/gitlab/circle/(none): circleMIT license
Do you want to license your code permissively under the MIT license? . . . y/(n): yCode of conduct
Do you want to include a code of conduct in gems you generate? . . . y/(n): yrubocop
Do you want to add rubocop as a dependency for gems you generate? . . . y/(n): ygemspec の更新
gemspec の
TODO
を確認し、必要に応じて記載を更新します。また、処理に必要な gem の依存関係を記載します。
gemspecspec.add_dependency "[GEM_NAME]"更新後、
bundle install
します。GitHub の設定
.gitignore
.gitignore
にGemfile.lock
を追加します。.gitignoreGemfile.lock詳しいことは「gem開発においてGemfile.lockをコミットするかどうか 」をご参照ください。
master -> main
このバージョンだと、デフォルトのブランチ名が
master
ですが、今はmain
を使うべきだと思うのでブランチ名を修正します。git add -A git commit -m "initial commit" git checkout -b main git branch -D masterremote add
GitHub に新規リポジトリを作成し、作成中の gem プロジェクトとリンクさせます。
git remote add origin https://github.com/[YOUR_ID]/[YOUR_GEM_NAME].git git branch -M main git push -u origin mainCircle CI
Circle CI にログインし、デフォルトで作成されている
.circleci/config.yml
でセットアップを実行します。ブランチ保護
GitHub のブランチ保護設定に main ブランチを追加しておきます。
処理の実装
lib
配下の[YOUR_GEM_NAME].rb
に処理を書いていきます。コンソール
挙動確認でコンソールを叩きたいときは、次のコマンドで irb を起動できます。
./bin/console irb(main):001:0>テスト & 静的解析
次のコマンドで
rspec
とrubocop
(デフォルトのタスク)が実行されます。bundle exec rake公開
公開手順の公式ドキュメント:こちら
RubyGems.org アカウント作成
gem の公開には RubyGems.org のアカウントが必要です。
rake build
アカウント作成後、以下のコマンドで公開に必要な
pkg/xxx.gem
ファイルをビルドします。rake build [YOUR_GEM_NAME] 0.1.0 built to pkg/[YOUR_GEM_NAME]-0.1.0.gem.gem push
次のコマンドで作成した
pkg/xxx.gem
ファイルをプッシュします。gem push pkg/[YOUR_GEM_NAME]-0.1.0.gemRubyGems.org のメールアドレスとパスワードを聞かれるので、それぞれ入力します。
Enter your RubyGems.org credentials. Don't have an account yet? Create one at https://rubygems.org/sign_up Email: xxxxx@example.com Password: Signed in. Pushing gem to https://rubygems.org... Successfully registered gem: [YOUR_GEM_NAME] (0.1.0)
Successfully registered
が表示されれば完了ですReferences
- 投稿日:2021-01-22T00:01:25+09:00
MVCモデルについて
学習を始めてしばらく経ったので復習をかけてアウトプットします。
MVCモデルとは
モデル(Model)の頭文字の「M」、ビュー(View)の頭文字の「V」、コントローラー(controller)の頭文字の(C)から「MVC」と呼びます。
それぞれの役割ごとにModel, View, Controllerに分割して作業を行います。
それぞれの持つ役割とは,
Model --> アプリの中で扱うデータを保持、操作、システムの設計や機能をどうするか決める
View --> HTMLなどの実際の見た目を司る部分。受け取ったデータを表示したり、入出力といった機能を処理する
Controller --> ユーザーからのリクエスト(入力)に基づき,ModelとViewを呼び出して処理し、その結果を返す
Rubyにおいて実装箇所がそれぞれ分かれているためそれぞれの役割と関連性を覚えることが重要です。
図2においてユーザーから入力があった時のMVCの流れを図にしました。
#MVCモデルでの処理の流れ
Model --> 受け取った命令を元に実際にデータの処理を行う
View --> 処理を行ったModelの状態を表示する
Controller --> ModelとViewに処理を分担する
例えば、ファーストフード店があったとします。
接客担当Vさん(View)がお客様(User)から受け取った注文を厨房に伝達する係員Cさん(Controller)に伝えます。そしてCさんが調理担当のMさんたち(Model)に注文がハンバーガーなのかポテトなのかを指示し、それぞれの担当のMさんが作った料理をVさん経由でお客様に渡すというのが処理の流れになります。このような役割分担が各機能ごとに存在するので分業して作業をしやすく変更・修正があった場合の影響が出にくくなっています。
今回の記事は以上になります.
図解を作る技術が発展途上のため見ずらかったらすみません。
間違っている点や理解が不十分な点等あればご指摘いただけると助かります。.