- 投稿日:2020-07-09T22:13:56+09:00
find_or_create_by
find_or_create_by
引数の条件に指定するデータがあった場合はそのデータを返します。無かった場合は新規作成します。
def find_or_create_by(attributes, &block) find_by(attributes) || create(attributes, &block) endメリット
結果が冪等になる。
冪等とは何度行っても得られる結果が等しいこと。すでに指定するデータが存在した場合は新規作成をしないので、
find_or_create_byを繰り返したとしても、得られる結果が等しいです。対してcreateメソッドだった場合は、
繰り返した分だけ新規作成が行われるので冪等ではないと言えます。
- 投稿日:2020-07-09T21:22:14+09:00
RailsとAjaxを使ったいいね機能の非同期通信
転職活動用に個人アプリを開発中です。
今回、RailsとAjaxを使って、いいね機能の非同期化を行いました。AjaxではjQueryを使うため、jQueryを使えるようにしておく事前準備が必要です。それは参考記事を見てください。以下の記述はそれが設定済みのうえでの話です。
実現した機能
・「いいね」ボタンを押すとリロードせずに「いいねを取り消す」に表示が変わる
・「いいね」ボタンを押すとリロードせずにlikesテーブルにデータが1つ追加される
・「いいね」ボタンを押すとリロードせずにいいね数が1つ増える
※その逆もしかりこのコードでうまくいきました
コントローラー(likes_controller.rb)
likes_controller.rbclass LikesController < ApplicationController def create @post = Post.find(params[:post_id]) @like = current_user.likes.build(post_id: params[:post_id]) @like.save @likeCounts = Like.where(post_id: params[:post_id]) end def destroy @post = Post.find(params[:post_id]) @like = Like.find_by(post_id: params[:post_id], user_id: current_user.id) @like.destroy @likeCounts = Like.where(post_id: params[:post_id]) end end個別の投稿ページ(上記の画像のページ)
show.html.haml.like = render partial: "likes/like", locals: {post: @post}部分テンプレート(_like.html.haml)
_like.html.haml- if user_signed_in? - if current_user.already_liked?(post) = button_to 'いいねを取り消す', post_like_path(post_id: post.id, id: post.likes[0].id), method: :delete, remote: true - else = button_to 'いいね', post_likes_path(post.id), method: :post, remote: true .likeCounts いいね数: = post.likes.count更新したい部分のビュー(いいねしたとき)
create.js.erb$('.like').html("<%= j(render partial: 'likes/like', locals: {post: @post}) %>");更新したい部分のビュー(いいねを取り消すとき)
destroy.js.erb$('.like').html("<%= j(render partial: 'likes/like', locals: {post: @post}) %>");JavaScriptが動く仕組み
・
link_to
やbutton_to
には:remoteオプション(remote: true
)がある。button_to
にremote: true
を追加することで、js形式のリクエストを送信できるようになる。= button_to 'いいね', post_likes_path(post.id), method: :post, remote: true参考:Railsガイド
非同期通信の流れ
1.「いいね」ボタンを押す
2.下記のリンクでlikes#create
にjs形式でリクエストが飛ばされる= button_to 'いいね', post_likes_path(post.id), method: :post, remote: true3.likesコントローラーのcreateアクションが動き、いいねが保存される。Likeモデルを介してデータベースに追加される(リロードせずに)
4.更新したい部分のページcreate.js.erb
,destroy.js.erb
がレスポンスとして返される。.html
(jQueryのhtmlメソッド)は、.like
(likeクラス)の部分をhtmlの後ろの( )内に置き換える役割をはたす。今回苦労したところ
1.部分テンプレートの理解
create.js.erb$('.like').html("<%= j(render partial: 'likes/like', locals: {post: @post}) %>");partialオプション:部分テンプレートの呼び出しを行う。今回はlikesフォルダの_like.html.hamlを呼び出したいので
likes/like
となる。localsオプション:部分テンプレート内で{ }内の左辺が変数として使えるようになる。今回でいうと
post
が変数として使えるようになる。右辺の@post
は何かというと、右辺の@post
が左辺のpost
に代入して、それが変数として使えるようになる。右辺の@post
はどこからきているかというと、postsコントローラのshowアクションで定義しているので、そこからきている。posts_controller.rbdef show @post = Post.find(params[:id]) Like.new end2.
_like.html.haml
のbutton_to
のpathの設定
ずっとこのエラーに悩まされていました。ActionView::Template::Error No route matches (中略) missing required keys: [:id])この記事を見つけてようやく下記のように記述して解決できました。
= button_to 'いいねを取り消す', post_like_path(post_id: post.id, id: post.likes[0].id), method: :delete, remote: true解決はしたものの、この部分
id: post.likes[0].id
がまだちゃんと理解できていません。
1つの投稿に複数のいいねがついていたとして、その最初のいいねのidを取得している?今考えてみると、確かに1つの投稿に複数のいいねがある場合、「どのいいねを取り消すの?指定してくれないとわからないよ」と言われても無理ないなと思いました。
だとすると、必ずしもcurrent_userの付けたいいねではなく、他の人の付けたいいねを取り消してしまう?
まだ修正する必要があるかもしれません?
(追記)
Sequel Proで確認したところ、他の人のいいねを取り消してしまうことはなく、ちゃんとcurrent_userのいいねが取り消されていました。
一応いいねを消せることは消せます。
この点が明らかになったらまた追記します。参考記事
Railsで remote: true と js.erbを使って簡単にAjax(非同期通信)を実装しよう!(いいね機能のデモ付)
【Rails×Ajax】いいね機能ハンズオン
Railsでいいね機能を実装。Ajaxを使い非同期対応。で
- 投稿日:2020-07-09T21:00:30+09:00
Digdag公式ドキュメントからDigdagを学ぶ-アーキテクチャ
#目次
Getting started
Architecture
Concepts
Workflow definition
Scheduling workflow
Operators
Command reference
Language API -Ruby
REST API
Internal architecture
Release NotesDigdag Architecture
Automating workflow with Digdag
ワークフローは手動の動作を自動化します。
一連のタスクをワークフローとして定義します。
Digdagは実行し続けます。タスクはオペレータープラグインを使用して定義されるため、中央のワークフローエンジンから多数の種類のシステムをコントロールできます。プラグインのランタイムフレームワークとして、Digdagはワークロードの自動化に関する残りの問題を処理し、自動化に集中できるようにします。
タスクが失敗した場合、Digdagはアラートを送信します。ワークフローが想定時間内に完了しない場合、Digdagは通知を送信します。
タスクは、ローカルマシン、分散サーバー、またはDockerコンテナーで実行できます。グループによるタスクの組織化
複雑なワークフローを自動化すると定義はすぐに複雑になります。 Digdagを使用するとタスクをグループに整理できます。
定義を確認する時に概要から見て詳細に移ると思います。
図の上の部分が概要部分でやろうとするのがデータ準備・分析・評価の流れだとすぐわかります。その後各グループの詳細を見ることで開発中デバッグとレビューが簡単になります。管理者は本番環境で何が起こっているのか問題を修正する方法は何かすぐわかります。依存する兄弟タスクがない場合、またはすべての兄弟タスクが正常に完了した場合にタスクが開始されます。
グループの親タスクが実行されるとその子タスクが実行されます。それらのすべてが正常に完了すると親タスクも正常に完了します。子タスクが失敗すると失敗した子タスクとその親タスクも失敗します。
ルートタスクが完了するかもしくは失敗すると実行全体が終了します。Parameters
タスクのグループ化はタスク間でパラメーターを渡すためにも使用されます。
親タスクは子タスクのため変数をエクスポートできます。(例:UNIXシェルのエクスポートコマンドが環境変数を設定するように)。親タスクは実行時に子タスクを生成できるため前のタスクの結果に応じてさまざまなタスクを実行できます。Workflow as code
Digdagワークフローはコードで定義されます。これによりソフトウェア開発のベストプラクティス(バージョン管理、コードレビュー、テスト、プルリクエストを使用したコラボレーション)がもたらされます。ワークフローをgitリポジトリにプッシュすると誰でもそれをプルして同じ結果を再現できます。
Running with local mode
Digdagは、単一ファイルの実行可能コマンドです。
新しいワークフローの作成と実行はMakefileと同じくらい簡単です。
*.dig
拡張子ファイルはワークフロー定義に使用されます。
digdag run my_workflow.dig
コマンドはワークフローを実行します。ローカルマシンでワークフローを開発してテストが終わったらワークフローを定期的に実行するためにサーバーにプッシュする必要があります。
Running on a server
同じディレクトリに存在する
* .dig
ファイルとその他のファイルはプロジェクトと呼ばれます。
全てのプロジェクトをDigdagサーバーにプッシュしてその結果サーバー上でワークフローを実行できるようになります。
少し早いですが、前回作ったWorkflowをサーバーにPushしたら以下のようになります。Digdagサーバー起動$ digdag init mydag $ cd mydag $ digdag run mydag.dig $ digdag server --memoryWorflowにProject追加$digdag push mydag 2020-07-09 20:39:20 +0900: Digdag v0.9.41 Creating .digdag/tmp/archive-3560803829245476890.tar.gz... Archiving mydag.dig Workflows: mydag.dig Uploaded: id: 1 name: mydag revision: b8b9abb8-b156-4089-a009-a01aa0337d9f archive type: db project created at: 2020-07-09T11:39:21Z revision updated at: 2020-07-09T11:39:21Z Use `digdag workflows` to show all workflows.Running tasks on Docker
Dockerを利用してコンテイナー中のタスクを実行できます。
dockerオプションが設定されていたらタスクはDockerコンテイナーで実行されます。まだ詳細タスクについて学んでないので以下のコードの説明はWorkflow definition部分で説明する予定
_export: docker: image: ubuntu:14.04 +step1: py>: tasks.MyWorkflow.step1Digdagは、プルされたイメージをキャッシュして再利用します。デフォルトでDigdagは更新があった場合でもキャッシュされたイメージを一貫して使用します。 pull_always:trueオプションを設定してDigdagが更新をチェックしタスクが開始されるたびにタグの最新のイメージをプルすることができます。
_export: docker: image: ubuntu:latest pull_always: true +step1: py>: tasks.MyWorkflow.step1
- 投稿日:2020-07-09T19:36:26+09:00
Digdag公式ドキュメントからDigdagを学ぶ-Getting started
Digdagについて
DigdagはOpenソースのマルチクラウドワークフローエンジンの事です。
簡単に言うとなんなかの仕事を順序に処理する流れを手伝ってくれるツールかと思いました。目標
Digdagについての本などがないためDigdagの公式サイトのドキュメントを翻訳しながらQiitaに整理したいと思います。
http://docs.digdag.io/architecture.html
ドキュメントは英語になっています。
低い英語力から小学生レベルの日本語に翻訳しながら勉強するので誤訳などあると思います。
今日はGetting Started部分からやります。
DigdagのRubyを使ってRailsにバッチを作るまでが最後の目標になります。#目次
以下のような内容になります。
Getting started
Architecture
Concepts
Workflow definition
Scheduling workflow
Operators
Command reference
Language API -Ruby
REST API
Internal architecture
Release NotesGetting started
1. 最新バージョンのDigdagダウンロードと設置
Digdagは実行ファイルです。
curl
コマンドを使って~/bin
にファイルを設置できます。$ curl -o ~/bin/digdag --create-dirs -L "https://dl.digdag.io/digdag-latest" $ chmod +x ~/bin/digdag $ echo 'export PATH="$HOME/bin:$PATH"' >> ~/.bashrc $ source ~/.bashrc
digdag --help
が実行できれば環境設定完了です。zshを使う方は
~/.bashrc
を~/.zshrc
に変更してください。Windows
PowerShell -Command "& {[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::TLS12; mkdir -Force $env:USERPROFILE\bin; Invoke-WebRequest http://dl.digdag.io/digdag-latest.jar -OutFile $env:USERPROFILE\bin\digdag.bat}"setx PATH "%PATH%;%USERPROFILE%\bin"2. サンプルを実行してみる
digdag init <dir>
コマンドはサンプルWorkflowを生成する。$ digdag init mydag $ cd mydag $ digdag run
digdag init mydag
コマンドで以下のようなサンプルコード(mydag.dig)が生成されるmayday.digtimezone: UTC +setup: echo>: start ${session_time} +disp_current_date: echo>: ${moment(session_time).utc().format('YYYY-MM-DD HH:mm:ss Z')} +repeat: for_each>: order: [first, second, third] animal: [dog, cat] _do: echo>: ${order} ${animal} _parallel: true +teardown: echo>: finish ${session_time}次回はArchitecture
- 投稿日:2020-07-09T19:03:04+09:00
【徹底解説】初心者必見の関数(メソッド)の理解の仕方
元の投稿
プログラミングの入門をする上で最も大事と言っても過言ではない関数またはメソッド(以下、どちらも関数と呼びます)
皆さんは関数と聞くと何を思い浮かべますか?
一般的には、数学の授業で聞く言葉だと思います。
ではどうして、プログラミングの世界でメソッドの事を関数と呼ぶことになったのでしょうか?
それは数学の関数と概念が非常に似ているからです。
そこで、まずは数学的な関数を見てみましょう。数学アレルギーの人も拒絶せず難しい話はしませんので、読み進めてもらえると嬉しいです。
まず、関数とは何でしょう?
関数とはある任意のxを与えると必ず1つのy(解)を返してくれるものです。ちょっと言葉だけでは難しいですね。
それでは、数学的な関数とは代表的なものに何があるでしょうか?
私が一番はじめに思い浮かべる関数は
y = ax + bです。これは一次関数と呼ばれるものですがaとbは定数(任意で数を決めれる)ので具体的に
y = 2x + 3を見てみましょう。
この関数はxを指定するとある数字が答えを出してくれます。例えば、x = 3であれば yの値は9になります。これはいろんな数字に当てはめれますよね。
なので、関数とは特定のXを与えると1つのYを返してくれるものです。
この関数のようなものは数学に限られてるものではありません。
例えば、食材を与えると美味しい料理を作るシェフがいるとします。このシェフはある意味、関数のような働きをしていると言えましょう。
具体的にはこのシェフに「人参、じゃがいも、牛肉、カレー粉」をXとして、渡してあげると、このシェフはカレーというYの値を返してくれます。
このようなXを与えるとYを返すというのが、一般的な関数の概要です。
なので、プログラミング的な関数(メソッド)も同じだと言えます。
ただ、プログラミングでは上記のXを引数と呼び、Yを戻り値のといいます。
それでは実際のコードを見ていきましょう。
今回はRubyコードを使用していますが、主要なプログラミング言語ではこの概念は変わりません。
それでは与えられた2つの数字(引数)を足し算をするメソッドを作成しましょう
# メソッド名はadd # 引数はa, b # どんなメソッドを作るか、どんな引数を引き受けるかは自分で決めるので、 # メソッド名と引数の名前は自由に名前を決めることが出来ます。 # メソッドの定義(作成 def add(a, b) return a + b end # メソッドの呼び出し(使用) add(3, 2) # =>戻り値は5になるこのコードを図式化すると以下のようになります
ここで新しく紹介した概念が
「呼び出しのコードそのものが戻り値に変わる」
ということです。これは非常に大事な概念なのでしっかりと理解してください。
つまり、
result = add(2, 3)というコードは
result = 5というコードとしているのと全く同じです。
ここで、どうして 5 と直接書くのではなく add(2,3) と書くのかというといくつか理由があります
まず、この例題では足し算をするメソッドを使用しているので
頭の中で5とすぐに戻り値を予想できますがこれがすごく複雑な処理だと
戻り値が予想できないのでメソッドを使用しないといけません。
次に、今回の場合では引数(a, b)が予め決められていますが
これは実際には変数になっていたりしますのでメソッドを使用する前に答えを予想することができなくなります。
ここまでで、メソッドの基本的な概念は終わりです。
プログラミングではたくさんの関数(メソッド)を使用します。
書いているもののほとんどが関数と言っても過言ではありません。
関数を定義することも多々ありますが、大きくは他人が作成した関数をしようするということがほとんどです。
その際に、引数として何が必要でどのような戻り値をくれるのかという概念で関数をみると
簡単に理解して関数の詳細を理解しなくても使用することが出来ます。
なので、関数(メソッド)を使用または定義する際は引数と戻り値に注目してみましょう。
- 投稿日:2020-07-09T18:44:59+09:00
Enumの設定ミス。なぜかEnum指定の列からデータが取れない…
発生した背景
※備忘録として記録します(ネタ的にはしょぼいです…)
以下のようなモデルにEnum設定したとき、データが取り出せない。table.rbclass ColorManage < ApplicationRecord enum color_type: { single: 0, double: 1, graphic: 2 } (省略)(前提)singleというラジオボタンを押すと、0が入力されるようにする。
color-edit.html.erb<!-- カラータイプ、どの設定にするか。--> <%= color_manage_record.radio_button :color_type, :single ,class:"color-form__button" %> <%= color_manage_record.label :color_type, "single-color", {class: "color-form__tag"} %>問題点> 画像のとおり、color_typeには"ゼロ"で入力されていますが、モデル抽出して、列値を取得しようとしてもnullで返ってくる
環境
項目 内容 OS.Catalina v10.15.4 Ruby v2.5.1 Ruby On Rails v5.2.4.3 MySQL V5.6 対応手順
原因)テーブルの定義がstringだったので、enumを以下のように定義しなおしました。ポートフォリオなので、恥ずかしながら、設計側を変えた次第です。
test.rbenum color_type: { single: "single", double: "double", graphic: "graphic" }これで解決しました。
以上です。
- 投稿日:2020-07-09T18:33:30+09:00
Timeオブジェクトの次の値ってどうやってだすのが正しい?
概要
RubyでTimeオブジェクトを扱ってると境界問題にぶち当たる。
普通にやってるとRangeオブジェクトなりを使ってそこまで問題になることはないが、普通じゃないやり方をしていて躓いた。環境
Ruby: 2.6.2
Rails: 5.1.2そもそもハマった問題
Time.now.end_of_day => 2020-05-15 23:59:59 +0900これの次の値を取りたい。
※ end_of_dayはわかりやすいから使ってるだけであって、とある日の先端、終端が欲しいわけではない。飽くまでもTimeオブジェクトの次の値真っ先に思いついたのがこれ
Time.now.end_of_day + 1 => 2020-05-16 00:00:00 +0900ただ、これは間違い
(Time.now.end_of_day + 1).iso8601(3) => "2020-05-16T00:00:00.999+09:00"
+ 1
は飽くまでも1秒加算であって、次の値に移行するわけではないので使えない。Timeクラスを漁ってるとすごくそれっぽいメソッドを見つけた
https://docs.ruby-lang.org/ja/latest/method/Time/i/succ.htmlTime.now.end_of_day.succ (pry):109: warning: Time#succ is obsolete; use time + 1 => 2020-05-16 00:00:00 +0900しかし、時代遅れだから使うなって怒られる上
+ 1
と同じことしてるだけらしい。だめ。解決方法
結局良さげな方法はわからなかったからゴリ押し
例の問題だと少数9桁までしか見ていない
(Time.now.end_of_day + 1).iso8601(10) => "2020-05-16T00:00:00.9999999990+09:00"つまり、1ナノ秒加算してやればいいわけだ
(Time.now.end_of_day + 1/1000000000.0).iso8601(9) => "2020-05-16T00:00:00.000000000+09:00"できた!
おまけ
Time.now.iso8601(10) => "2020-05-15T19:56:55.4979370000+09:00" Time.new(2020, 5, 16, 16, 59, 59.3).iso8601(9) => "2020-05-16T16:59:59.299999999+09:00" Time.parse("2020-05-16T16:59:59.3+09:00").iso8601(9) => "2020-05-16T16:59:59.300000000+09:00" Time.parse("2020-05-16T16:59:59.35555555555555555555+09:00").iso8601(20) => "2020-05-16T16:59:59.35555555555555555555+09:00"だめだった
結論
- Timeオブジェクト内の小数秒の桁数は無限に持てる
- そのため次の値という概念がそもそも無い
- ただ、Timeオブジェクトの生成の仕方に依存するので、DBから引っ張ってくるならその有効桁数を考慮してやれば無理やり作れなくはない
- そもそも素直にRangeオブジェクトを使うなりして比較すべき
- 投稿日:2020-07-09T18:13:18+09:00
Rails5でECサイトを作る⑥ ~seedデータ投入~
はじめに
架空のベーカリーで買い物できるECサイトを作るシリーズ、Rails5でECサイトを作る⑤の続きです。
この後の実装を続けていく上で、初期データを入れておいた方が何かと都合が良さそうなので、一旦そちらを優先することにしました。複数のseedファイルを管理する
あくまで表示が正しくできるか確認するためのデータなので、最小限作っておけば良いと思います。しかし、Model数が多い分、やはり一つでファイルで全て済まそうとすると記述量が膨大になってしまいます。
そこで、新たにseedsというフォルダを作り、その中に各Model毎の初期データを入れることにしました。(一つのseeds.rbファイルで済ませたい人はこちら)$ cd work/fumizuki/db $ mkdir seeds $ cd seeds $ touch customer.rb $ touch address.rb $ touch genre.rb $ touch product.rb $ touch order.rb $ touch order_item.rbファイル群の読み込み、Adminデータ作成
作成したファイル群をseeds.rbファイルから読み込めるようにします。これでrails db:seedを叩いた時にseedsフォルダ内のデータも認識されます。
ここで注意が必要な点は、親Modelを上に記述することです。ファイルの読み込みは上の行から順番に行われるため、子Modelを先にしてしまうと「Customerデータがありません!」とエラーになります。db/seeds.rbrequire './db/seeds/customer.rb' require './db/seeds/address.rb' require './db/seeds/genre.rb' require './db/seeds/product.rb' require './db/seeds/order.rb' require './db/seeds/order_item.rb' Admin.create!( id: 1, email: 'admin@user', password: 'adminuser', password_confirmation: 'adminuser' )Adminのデータもこちらに書いておきました。管理者のデータは1件あれば十分で、わざわざ別ファイルに分けるほどのコード量ではないので。
データをたくさん作る
Address
db/seeds/.rbAddress.create!( [ { id: 1, customer_id: 1, addressee: '稲継亜矢子', post_code: '1111111', address: '月川県岩青山町四南寺2-15', }, { id: 2, customer_id: 2, addressee: '鈴鹿由美子', post_code: '2222222', address: '細野県城見市世史が丘3-1-7', }, { id: 3, customer_id: 3, addressee: '関沢智恵美', post_code: '3333333', address: '赤田県初山市十越智町6-12', }, { id: 4, customer_id: 4, addressee: '巻譲', post_code: '4444444', address: '根野県羽島市後目台8-12', }, { id: 5, customer_id: 5, addressee: '岡崎弥生', post_code: '5555555', address: '古岡県紫波市刈唯山3-5-2', }, ] )Customer
db/seeds/.rbCustomer.create!( [ { id: 1, email: '1@1', family_name: '長岡', family_name_kana: 'ナガオカ', first_name: '聡美', first_name_kana: 'サトミ', post_code: '1111111', address: '北岡県乙西川市馬城寺2-6-1', tel: '11111111', is_active: true, password: '111111', password_confirmation: '111111', }, { id: 2, email: '2@2', family_name: '野崎', family_name_kana: 'ノザキ', first_name: '健吾', first_name_kana: 'ケンゴ', post_code: '2222222', address: '鳥川県盤上山市升沖ヶ丘1-15', tel: '22222222', is_active: true, password: '222222', password_confirmation: '222222', }, { id: 3, email: '3@3', family_name: '妹尾', family_name_kana: 'セオ', first_name: '千代美', first_name_kana: 'チヨミ', post_code: '3333333', address: '仁田県那珂和町山巻学園3-2', tel: '33333333', is_active: true, password: '333333', password_confirmation: '333333', }, { id: 4, email: '4@4', family_name: '塚越', family_name_kana: 'ツカゴシ', first_name: '貴美', first_name_kana: 'タカミ', post_code: '4444444', address: '笠川県冬田市志林川町5-2-7', tel: '44444444', is_active: true, password: '444444', password_confirmation: '444444', }, { id: 5, email: '5@5', family_name: '鎌田', family_name_kana: 'カマタ', first_name: '幸宏', first_name_kana: 'ユキヒロ', post_code: '5555555', address: '早田県響山市大字威初2-16', tel: '55555555', is_active: true, password: '555555', password_confirmation: '555555', }, ] )Genre
db/seeds/.rbGenre.create!( [ { id: 1, name: '食パン', validity: true }, { id: 2, name: '総菜パン', validity: true }, { id: 3, name: '菓子パン', validity: true }, { id: 4, name: '限定', validity: true }, { id: 5, name: 'その他菓子', validity: true }, ] )Order
db/seeds/.rbOrder.create!( [ { id: 1, customer_id: 1, addressee: '稲継亜矢子', post_code: '1111111', send_to_address: '月川県岩青山町四南寺2-15', how_to_pay: true, order_status: 0, }, { id: 2, customer_id: 2, addressee: '鈴鹿由美子', post_code: '2222222', send_to_address: '細野県城見市世史が丘3-1-7', how_to_pay: true, order_status: 2, }, { id: 3, customer_id: 3, addressee: '関沢智恵美', post_code: '3333333', send_to_address: '赤田県初山市十越智町6-12', how_to_pay: true, order_status: 1, }, { id: 4, customer_id: 4, addressee: '巻譲', post_code: '4444444', send_to_address: '根野県羽島市後目台8-12', how_to_pay: false, order_status: 2, }, { id: 5, customer_id: 5, addressee: '岡崎弥生', post_code: '5555555', send_to_address: '古岡県紫波市刈唯山3-5-2', how_to_pay: true, order_status: 0, }, ] )OrderItem
db/seeds/.rbOrderItem.create!( [ { id: 1, order_id: 1, product_id: 10, quantity: 4, order_price: 270, make_status: 2, }, { id: 2, order_id: 1, product_id: 7, quantity: 6, order_price: 230, make_status: 1, }, { id: 3, order_id: 2, product_id: 2, quantity: 2, order_price: 260, make_status: 0, }, { id: 4, order_id: 3, product_id: 3, quantity: 6, order_price: 180, make_status: 1, }, { id: 5, order_id: 4, product_id: 4, quantity: 8, order_price: 370, make_status: 1, }, { id: 6, order_id: 5, product_id: 5, quantity: 10, order_price: 160, make_status: 2, }, ] )Product
db/seeds/.rbProduct.create!( [ { id: 1, name: 'ブリオッシュ', introduction: 'バターの風味豊かな食パンです。', genre_id: 1, price: 500, status: true, }, { id: 2, name: 'バゲット', introduction: '国産小麦100%のフランスパン。', genre_id: 1, price: 260, status: true, }, { id: 3, name: 'カレーパン', introduction: '中辛のカレーを、甘いパン生地と組み合わせました。', genre_id: 2, price: 180, status: true, }, { id: 4, name: 'ハンバーガー', introduction: '自家製のバンズに具材をたくさん挟み込みました。', genre_id: 2, price: 370, status: true, }, { id: 5, name: 'あんぱん', introduction: 'どこから食べても美味しい斬新なあんぱんです。', genre_id: 3, price: 160, status: true, }, { id: 6, name: 'クリームパン', introduction: '当店こだわりのカスタードをお楽しみください。', genre_id: 3, price: 170, status: true, }, { id: 7, name: 'パン・オ・ショコラ', introduction: '当店の一番人気です♪', genre_id: 3, price: 230, status: true, }, { id: 8, name: 'ラウゲン・ブロートヒェン', introduction: 'ドイツ風のもっちりパン。', genre_id: 4, price: 200, status: true, }, { id: 9, name: 'いちごのお花パン', introduction: 'ふんわりとした生地に苺の風味を加えました。', genre_id: 4, price: 180, status: true, }, { id: 10, name: 'モンブラン', introduction: 'ブリオッシュにマロンクリームを合わせてどうぞ。', genre_id: 5, price: 270, status: true, }, { id: 11, name: 'パンケーキ', introduction: '強力粉からつくるしっとりしたパンケーキです。', genre_id: 5, price: 150, status: true, }, ] )データをまとめて作成
もし見た目にこだわりがなく、「文月太郎1」「文月太郎2」のようなデータで構わない場合は、複数のデータを一気に作ることもできます。
db/seeds.rbAdmin.create!( id: 1, email: 'admin@user', password: 'adminuser', password_confirmation: 'adminuser' ) 50.times do |n| Customer.create!( email: "1@#{n}", family_name: "文月#{n}", family_name_kana: "フミヅキ#{n}", first_name: "太郎#{n}", first_name_kana: "タロウ#{n}", post_code: "1111111", address: "横岡県氷川市絵向寺#{n}丁目", tel: "11111111111", is_active: true, password: "111111", password_confirmation: "111111", ) Address.create!( customer_id: 1, addressee: "文月なな#{n}", post_code: '1111111', address: '三橋県東里見町松林2-15-#{n}' ) Genre.create!( name: "ジャンルその#{n}", validity: true ) Product.create!( name: "自家製パン#{n}", introduction: "#{n}倍美味しくなりました!(当社比)", genre_id: 1, price: 260, status: true, Order.create!( customer_id: 1, addressee: "文月花子#{n}", post_code: "1111111", send_to_address: "遊明県鳥窪町", how_to_pay: true, order_status: 1, ) OrderItem.create!( order_id: 1, product_id: 5, quantity: 10, order_price: 600, make_status: 1, ) end後記
seedデータはいつ入れるのが適切なのか、よく分かりませんがとりあえず入れました。Modelの設定を終えた段階で一通り作ってしまうのが、一番スムーズかも知れません。データが入っていなくてもアプリ自体は作れるので、余計に迷うところです。
アプリ開発をする上で、どのような順序で進めるのが最も効率的なのか判断しきれずに、かなりめちゃくちゃな順番でやっているのではという気がしています。このECサイトを仕上げたら、解説記事たちも順番を入れ替えて、サクサク実装できるチュートリアルにまとめたいと思います。
一番の問題は「完成までこぎつけるかどうか」ですけどね! 次回へ続く!
参考
- 投稿日:2020-07-09T16:47:20+09:00
Ruby 二次元配列
二次元配列とは?
2次元配列とは、プログラムで利用される配列において、配列の中に配列が入っている配列のことである。
ソースコード
fruits_price = [["apple", [200, 250, 220]], ["orange", [100, 120, 80]], ["melon", [1200, 1500]]] # 配列Key 合計額算出 fruits_price.each do |fruit| sum = 0 fruit[1].each do |price| sum += price end puts "#{fruit[0]}の合計金額は#{sum}円です" end結果
appleの合計金額は670円です orangeの合計金額は300円です melonの合計金額は2700円です説明
keyにフルーツの名前、valueにそのフルーツの値段が配列で複数
[["apple", [200, 250, 220]]Ruby each文
オブジェクト.each do |変数| 実行する処理1 実行する処理2 endこちらで要素を一つづつ取り出しています。
fruits_price.each do |fruit| sum = 0 fruit[1].each do |price| sum += price endここで、配列の中の価格が入っている配列に対して要素を取り出し、
合計(sum)に格納します。これで完成です。
- 投稿日:2020-07-09T16:37:51+09:00
Railsでyoutubeの動画を埋め込み表示させる方法(編集でも入力したURLを取得できる)
1 概要
railsでyoutubeの動画を埋め込み表示させたいなと思い、様々な記事を参考にして実装を試みました。ただ、参考記事通りでは自分の思い描いたような実装はできませんでした。それから試行錯誤を繰り返し、バグ等が出ず、編集画面でも入力したURLが生成されるやり方が分かったので、その実装方法を記載します。
1.1 YouTubeURLの種類
youtubeの動画は11桁の文字列で動画の識別を行っております。その11桁の文字列をyoutubeの埋め込み用のURLに貼り付けてあげれば、railsでも埋め込み動画を表示されるます。
youtubeのURLhttps://www.youtube.com/watch?v=0CqFEDzDkIA&t この文字列で動画の識別を行う →→ 「0CqFEDzDkIA&t」ただ、ここに大きな落とし穴があります。
上記URLが生成される条件として、youtubeの動画を0秒から開始する場合のみ、上記のURLが生成されます。
この条件を満たしていないと、さらに長いURLが生成されるので、参考記事 通り作成しても、埋め込み動画が表示されないバグが発生します。基準を満たしたURLであれば、参考記事でも正しく再生されます
下記の方法でyoutubeのURLを取得すると、動画識別の11文字のコードより長いURLが生成される
- 動画の再生を途中で止めた動画のURL
- 特殊な状況で動画を再生している動画のURL
(例:自身のお気に入り動画の再生画面からURLを取得する等)
(その他にもあるかもしれませんが、どちらにせよURLは長くなる方向で生成されます)これらを踏まえ、実装の段取りを説明していきます。
2. 実装
著者のバージョン
- ruby 2.5.1
- rails 5.2.3
- mysql 5.7
2.1 事前準備
まず、YouTubeの動画を投稿するだけのサンプルアプリを作っていきます。
ターミナル操作$ mkdir projects // ディレクトリは各自用意 $ cd projects $ mkdir sample_app $ cd sample_app $ $ rails new youtubetest -d mysqlバージョン指定したい場合は下記のように入力してください
rails -5.2.3- new youtubetest -d mysql
$ rails sサーバーを起動します。
サーバー立ち上げることができたか確認するため、http://localhost:3000 にアクセスする。いつもの画像が出れば起動は完了です。
2.2 Gem導入
私は、Hamlで書くことが多いので、
gem 'haml-rails'
を導入します。gemfilegem 'haml-rails'導入後はrailsをたち下げ、
bundle install
を行ってください。2.3 アプリの作成
ルーティングを記述します。
routes.rbRails.application.routes.draw do root to: 'products#index' resources :products, only: [:index, :new, :create,:edit ,:update, :destroy] endコントローラーを作成します。
ターミナル$ rails g controller productsproductsコントローラーに以下を追記してください。
class ProductsController < ApplicationController def index @products = Product.all end def new @product = Product.new end def create product.create(product_params) redirect_to root_path end def destroy product = Product.find(params[:id]) product.destroy end def edit @product = Product.find(params[:id]) end def update product = Product.find(params[:id]) product.update(product_params) end private def product_params params.require(:product).permit(:name, :youtube_url) end endモデルを作成します。
ターミナル$ rails g model productマイグレーションファイルに以下のように追加して下さい
db/migrate/xxxxxxxxxxxxxx_create_products.rbclass CreatePosts < ActiveRecord::Migration[5.2] def change create_table :products do |t| t.text :name # 追加 t.string :youtube_url # 追加 t.timestamps end end end
rails:db:migrate
をしましょう。ターミナル$ rails db:migrate下準備は終了です
ここからが一番重要な工程になります!!トップ画面のビューファイルを作ります。
下記コマンド入力してください。ターミナル$ touch app/views/products/index.html.haml $ touch app/views/products/new.html.haml $ touch app/views/products/edit.html.haml ※ 上から順番に打ち込んでくださいトップ画面のビューファイルを作ります。
index.html.haml
に下記のコードを追記してください。index.html.haml.contents - @products.each do |product| .content_post = product.name .content_post %iframe{src: "https://www.youtube.com/embed/#{product.youtube_url[32..42]}",allow: "accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture", allowfullscreen: "", frameborder: "0", height: "315", width: "560"}下記コードは、埋め込みコードの基盤となるコードです。
https://www.youtube.com/embed/
このコードの後ろに、#{post.youtube_url[32..42]}
を追記してあげることで、変則的な状態で生成されたURLでも正常に再生できるようになります。補足説明%iframe{src: "https://www.youtube.com/embed/#{product.youtube_url[32..42]}"、以下省略} # 下記のコードを追記する "#{product.youtube_url[32..42]}" # 動画の識別をする11桁の文字列を取得している続いて、投稿画面と編集画面のviewを作成します。
new.html.hamlと
edit.html.haml`に下記コード追記してください
(ここの工程ではパーシャルテンプレートを用いて大丈夫です)new.html.haml&edit.html.haml.new-contents .new-contents__content = form_with(model: @product, local: true) do |form| contents-group = form.label :name, "名前" = form.text_field :name, placeholder: 'name' contents-group = form.label :youtube_url, "YouTubeのURL" = form.text_field :youtube_url, placeholder: 'youtube_url' = f.submit '投稿する'以上で完成となります!!
少し埋め込みコードに記述を加えるだけで、どんな状態のURL(youtubeに限る)でも動画の埋め込みが正しくでき、動画が再生できると思います。参考記事
- https://qiita.com/Kairi_Yasunnde/items/8e931a4670549ba8237e
- https://qiita.com/yuichisan65/items/9356a2822fb37e51b3b4
最後に
以上で、「Railsでyoutubeの動画を埋め込み表示させる方法」の説明を終わりたいと思います。間違っている点がありましたらご指摘頂けると助かります。
最後までご覧いただき、ありがとうございました。
- 投稿日:2020-07-09T15:56:50+09:00
【EMMET 記法】 基本 よく使うやつ エメット記法 まとめ
【メリット】
■ コーディングが早くなります。
■ ミスが少なくなります。【開発環境】
■ Mac OS catalina
■ VS code【やっていきましょう】
HTML版
div.hoge
hoge.html<div class="hoge"></div>div#hoge
hoge.html<div id="hoge"></div>div*3
hoge.html<div></div> <div></div> <div></div>div>h2
hoge.html<div> <h2></h2> </div>CSS版
h100
hoge.cssheigh: 100px;w100
hoge.csswidth: 100px;bc
hoge.cssbackground-color: #fff;c
hoge.csscolor: #fff;ta
hoge.csstext-align: center;m10
hoge.cssmargin: 10px;p10
hoge.csspadding: 10px;【まとめ】
■基本的に使うやつなので、他にもたくさんあります。
■実装5倍くらいのスピードになるので、是非【合わせて読みたい】
■ 【メソッド集】 rails メソッド まとめ 基礎 随時追加
https://qiita.com/tanaka-yu3/items/89abad875187494bec53■ 【Javascript】 メソッド まとめ 基礎基本コード メモ
https://qiita.com/tanaka-yu3/items/2438798d159fa402b1d5■ 【Rails new】Ruby on rails アプリケーション作成
https://qiita.com/tanaka-yu3/items/3fe1ed2852c6513d3583■参考 emmet記法
https://tracpath.com/works/development/emmet-for-web-developers/
- 投稿日:2020-07-09T15:45:33+09:00
結局【rails db:migrate】は何をやっているのか?
Railsで当たり前のように使っているrails db:migrateですが実は何となく使っていて実際に何をしているか分かっていない方もいらっしゃるのではないでしょうか?
自分もつい最近までは何となく、あーmigrationファイルをデータベースに反映してるのね~程度にしか理解していませんでした。
しかし深くまで勉強し行くうちに、「あれ、結局Railsのそれぞれのコマンドって何をしてるんだろう」と思ったので今回記事にまとめました。
migrateはmigrationファイルの内容をDBに反映する行為
結論から言うと
migrateはmigrationファイルの内容をDBに反映する行為
になります。しかしこれだけでは弱いのでのでもう少し深堀していこうと思います。
MVCモデルについて
まずは基礎認識の部分ですが、Ruby on RailsはというフレームワークはMVCというモデルを使用しております。
ここでは詳細を省かせていただきますが、
- サーバーからのリクエストに応じてアクションを実行するController
- データベース(DB)とのやり取りを行うModel ## rails g model
- ブラウザ表示を担うView
という3つの部分から構成されます。
rails g model
migration(マイグレーション)を理解する前にまずはモデルの作成コマンドから紐解いていきましょう。
rails g modelコマンドを実行すると大きく分けてmodelファイルとmigrationファイルの2種類が作成されます(厳密にいうとさらにtestファイルなども自動作成されます)。
これらのファイルはそれぞれ
- migrationファイル→DBに変更を加える内容
- modelファイル→DBとRailsのアプリケーションを繋ぐ
といった役割があります。
特にここで作成されるモデルは全てApplicationRecordというクラスを継承しております。
models/user.rbclass User < ApplicationRecord # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable endさらにこのApplicationRecordクラスの親クラスはActiveRecord::Baseを継承しています。
models/application_record.rbclass ApplicationRecord < ActiveRecord::Base self.abstract_class = true endこのActiveRecordクラスはDBとやり取りする際に必要なSQL構文を翻訳する機能を持っています。
そのためいちいちSQL構文を書かずとも簡単にDBにアクセスしデータをいじくることができるのです。
Railsから入るとあまりなじみがないかもしれませんが、通常DBにアクセスしデータを操作するためにはSQLという別の言語を使って指示を飛ばさなくてはなりません。
SQL文の例-- テーブルを作成 CREATE TABLE USERS ( ID INT NOT NULL PRIMARY KEY, NAME VARCHAR NOT NULL AGE INT NOT NULL ); -- データを作成(railsではtable.create(value1, value2…)) INSERT INTO USERS VALUES (1,'イチハラ',''); -- データをすべて選択(railsではmodel.all) SELECT * FROM USERSしかしRailsではこのActiveRecordを使用することで自動でSQLに翻訳し、より直感的で簡単な構文でDBを操作することができるのです。
またこのActiveRecord::Baseクラスでは自動的にゲッターとセッターが定義されているため、意図的にattr_accessorなどを定義せずともインスタンスの値を参照することができます。
なるほど…
確かに便利だけどこれがゲッターとセッターを理解するのに苦しんだ訳か…rails db:migrate
rails db:migrateを実行すると作成されたmigrationファイルを基にDBに変更を加えます。今回の場合はmodel作成時のmigrateの為、DB上に新たにテーブルを作成します。
xxxxxxxx_create_users.rbclass CreateUsers < ActiveRecord::Migration[5.1] def change create_table :users do |t| t.string :name t.timestamps end end endActiveRecordによって作成されたテーブルは以下のような特徴を持ちます。
- テーブル名はmodelの複数形(Post → posts)
- id,created_atが自動作成
ちなみにrails g migrationによってmigrationファイルを作成した場合は自動的にchangeメソッドが定義されており、すでに作成されたテーブルに変更を加えることができます。
xxxxxxxx_oooo.rbclass PasswordDigestToUsers < ActiveRecord::Migration[5.1] def change add_column :users, :password_digest, :string end end終わり
以上がマイグレーションについてです。
あまり自信があるわけではないので、間違っていた李解説がおかしい部分があればご指摘いただけると幸いです!
- 投稿日:2020-07-09T13:08:30+09:00
(初心者向け)【Rails】時短テク!slimの導入方法と使い方
はじめに
Rubyのテンプレートエンジン
slim
の導入方法と使い方をご説明します
Railsでは、html.erb
というファイルでhtmlを書きますが、<h1></h1>
や<% %>
を毎回記入するのが少し面倒です。
slim
を利用すると、htmlをより簡潔に書けるため、開発にかかる手間を減らすことができます。※ erbとは
embedded Rubyのこと。Viewファイルの中の好きな場所でRubyのコードを実行できるようになります。1. slim 導入方法
- railsのディレクトリにある
gemfile
に、2つのgemを追加します。gem 'slim-rails' # railsでslimを利用するためのgem gem 'html2slim' # html.erbをhtmle.slimに変換するためのgem
- ターミナルで
bundle install
と打ち、gemの追加を反映させます。bundle install
- 以下のコマンドをターミナルに打ち、app/viewsディレクトリにある既存のhtml.erbファイルをhtml.slimに切り替えます。
bundle exec erb2slim app/views app/views
- slimファイルが追加されたことを確認したら、既存のerbファイルは邪魔なので削除します。
bundle exec erb2slim app/views app/views -d※ 念の為、
git commit
を使ってファイルの状態を記録することをオススメします。ファイルを削除して問題が生じても、git commit
前の状態に戻すことができます。git log #ハッシュ値を調べるgit reset --hard ハッシュ値 #出てきたハッシュ値を--hardの後に入力すると、指定したコミットまで戻ります。2. slim 書き方
基本的なslimの使い方を列挙します。
<% %>の書き方
- html
<% if %>
- slim
-
- if<%= %>の書き方
- html
<%= puts hoge %>
- slim
=
= puts hogeテキストの書き方
- html
<p>hoge<p>
- slim
|
p | hoge見出しタグの書き方
- html
<h2>hogehoge</h2>
- slim
<>は必要なし
h2 hogehogeidの書き方
- html
<div id = id></div>
- slim
#
# idクラスの書き方
- html
<div class = hoge></div>
- slim
.
.hogeコメントの書き方
- html
<!-- hoge -->
- slim
/
/hoge
htmlとslimを見比べると、非常にシンプルに書けることが分かります。
参考記事
より詳しい情報について知りたい方は、以下のURLをご参照ください。
- 【爆速で習得】Railsでslimを使う方法から基本文法まで
https://qiita.com/ngron/items/c03e68642c2ab77e7283
- git commitを使って変更内容をコミットする方法【初心者向け】
- 投稿日:2020-07-09T12:48:23+09:00
[Rails]カテゴリを選択するフォームを作りたい
こんにちは。
現在Railsで掲示板をつくっています。掲示板のスレッドをカテゴリで分類して表示したかったので、スレッドをたてる時にカテゴリーを選択するようにしようと思って実装しました。
最近Railsを触り始めたので詳しい人いたらマサカリおねがいします。
バージョンとか
Ruby 2.5
Rails 5.1DB・準備
モデル間の設定も忘れずに...
thread.rbclass Thread < ApplicationRecord belongs_to :categories endcategory.rbclass Category < ApplicationRecord has_many :thread endまずはカテゴリを登録する
カテゴリがないと始まらないので、登録しましょう。コンソールからでもいいのですが、今後カテゴリを追加していくと考えて、登録フォームを作ってしまいます。登録したら一覧ページに飛ぶ様にしてあります。
はじめに、routes,controllerを書いていく
- ルーティング
routes.rbRails.application.routes.draw do root 'thread#index' resources :thread #スレッドのルーティングも書いちゃいます resources :categories end
- コントローラ
categories.controller.rbclass CategoriesController < ApplicationController def new @category = Category.new end def create @category = Category.new(category_params) if @category.save redirect_to categories_path, notice: "登録しました" else render :new end end def index @categories = Category.all end private def category_params params.require(:category).permit(:name) end end
- 登録フォーム
new.html.erb<div class="col-sm-12"> <h2 class="text-center">カテゴリの追加</h2> <%= form_with model: @category, local: true do |f| %> <div class="form_input"> <%= f.label :name %> <%= f.text_field :name, class:"form-control" %> </div> <div class="form_action row"> <%= f.submit "登録する", class: "btn col-sm-12 submit_btn" %> </div> <% end %> </div>
- 一覧ページ
これはとりあえず表示できればいいかなと
index.rb<div> <% @categories.each do |category| %> <%= category.name %> <% end %> </div>スレッド投稿フォームをつくる
登録ができたので、あとはスレッドの投稿フォームでカテゴリを選べる様にします。
- コントローラ
threads_controller.rbclass ThreadsController < ApplicationController def new @thread = Thread.new end def create @Thread = Thread.new(board_params) if @thread.save redirect_to thread_path(@thread), notice: "投稿が完了しました" else render :new end end def show @thread = Thread.find(params[:id]) end private def board_params params.require(:thread).permit(:title,:body) end end
- 投稿ページ
collection_select
で選択フォームを作ることができます。使い方としては、こんな感じに使うのですが...
collection_select(オブジェクト名, メソッド名, 要素の配列, value属性の項目, テキストの項目 [, オプション or HTML属性 or イベント属性])
今回の例だと、
Category.all
が「要素の配列」の部分にあたりますね。
もしかしたら、Category.all
って書くよりもコントローラの方で変数に入れちゃってviewで使用。という様な形の方がいいのかもしれません。ここはだれか指摘していただけると助かります。
threads/new.index.erb<div class="col-sm-12"> <h2 class="text-center">スレッド立てる</h2> <%= form_with model: @thread, local: true do |f| %> <div class="form_input"> <%= f.label :title %> <%= f.text_field :title, class: "form-control" %> </div> <div class="form_input"> <%= f.label :body %> <%= f.text_area :body, class: "form-control" %> </div> <div class="form_input"> <%= f.label :category_id %> <%= f.collection_select :category_id, Category.all, :id, :name, :include_blank => "カテゴリを選択してください" %> </div> <div class="form_action row"> <%= f.submit "投稿する", class: "btn col-sm-12 submit_btn" %> </div> <% end %> </div>以下の様な感じで選択できるようになります。
おわりに
最後までみてくれてありがとうございました。
これからたくさん記事書いて、どんどんアウトプットしていこうと思います。
- 投稿日:2020-07-09T09:34:08+09:00
Mysql2::Error::ConnectionErrorを解決します
環境/バージョン
ローカルでやってます
Ruby v2.5.1
Rails v5.2.4
MySQL v8.0.19何が起こった?
railsプロジェクトを作成したあと、`rails s'してみたらこんなエラーに遭遇
Mysql2::Error::ConnectionError (Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)):どうやって解決した?
エラー文からみてわかる通り「あ、MySQL」かとすぐわかります。
ConnectionError
とあるので「繋がっていませんね〜」ってすぐわかります。
database.yml
を調べて見る。default: &default adapter: mysql2 encoding: utf8 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: root password: socket: /tmp/mysql.sock ---以下省略---ymlファイルのpasswordが抜けてる。
この間、MySQLにpassword設定するの忘れていたからでした。以前までは設定してなかったのでなくても接続できていましたが、設定したのもあって今回はうまく繋がってくれなかったみたいです。
default: &default adapter: mysql2 encoding: utf8 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: root password: password #追記 socket: /tmp/mysql.sockこの画面出るとホッとする。かわいい子供たち
最後まで読んでくれてありがとうございました。
少してもお役に立てれば嬉しいです。
- 投稿日:2020-07-09T07:14:22+09:00
基礎から学ぶ 人工知能の教科書 第2章 章末問題
はじめに
機械学習の勉強として、「基礎から学ぶ 人工知能の教科書」 を読んでいます。
この本の特徴は、章末問題に
Python
の簡単なプログラムが載っていてるところです。第2章 章末問題
ELIZA.rbLIMIT = 20 CYCLE = 5 count = 0 endcount = 0 puts('Dr>私はDoctor、お話を伺います') while endcount < LIMIT print('あなた>') inputline = gets.chomp.encode("UTF-8", "CP932", :invalid => :replace) if count >= CYCLE puts 'Dr>' << inputline << '、ですか...' count = 0 elsif inputline.include?('先生') puts 'Dr>私のことでなくあなたのことを話しましょう' elsif inputline.include?('母') puts 'Dr>あなたのお母さんについて話してください' elsif inputline.include?('父') puts 'Dr>あなたのお父さんについて話してください' elsif inputline.include?('意見') puts 'Dr>私の意見を聞きたいのですか?' elsif inputline.include?('が心配です') puts 'Dr>' << inputline.sub(/が心配です/, 'は心配ですか?') else puts 'Dr>続けてください' end count += 1 endcount += 1 end puts('Dr>それではそろそろ終了しましょう。おつかれさまでした。')簡易版ELIZAを作成する問題です。
CP932.rbinputline = gets.chomp.encode("UTF-8", "CP932", :invalid => :replace)
Windows10
の場合、文字コードを変換する処理が必要になっています。
AtCoder
では、こういう処理が無いので新鮮です。
但し、コマンドプロンプトのバグ対応で、レガシ コンソールを選択する必要があります。
まとめ
- 第2章まで読んだ
- G検定は難しかった
- 投稿日:2020-07-09T04:03:36+09:00
def initializeでちょっとだけハマった話
initializeはnewした時点で値がsetされる
クラスメソッドでinitializeにsetした値を参照したい時ハマってしまった
class Hoge attr_accessor :aa def initialize @aa = 'aa' end def self.bb @aa end end p Hoge.bb # => nilHoge.newしていないので値をセットできていません、
よってnilが返るclass Hoge attr_accessor :aa def initialize @aa = 'aa' end def bb @aa end end hoge = Hoge.new p hoge.bbインスタンスメソッドを利用すれば値を参照できる(当たり前ですよね)
クラスメソッドで値を使いたい時は
initialize使わず直接インスタンス変数に値をセットしましょう。class Hoge @aa = 'aa' def self.bb @aa end end p Hoge.bb #=> "aa"クラスメソッドで使うのかインスタンスメソッドで使うのか、
用途に合わせて、initializeの中身は意識しないといけないんだなと学んだハマりでした。日々精進
- 投稿日:2020-07-09T02:23:16+09:00
Rubyのハッシュとシンボルについて
プログラミングの勉強日記
2020年7月9日 Progate Lv.162
RubyⅠ RubyⅡ
今日からRubyの勉強を始める。1ヶ月後にでRuby on Railsを用いてアプリを作れるように勉強していく。Rubyとは
Qiitaでは初めてRubyについて触れるので、最初に簡単にRubyの説明と簡単な使い方について説明する。
RubyはWebアプリケーションのシステムを作るためのプログラミング言語で、似たような言語ではPHPやPythonなどがある。
本題のハッシュに入る前に簡単にRubyの使い方について説明する。変数の定義
変数名=値
で変数の定義を行うことができる。基本的な使い方は他のプログラミング言語と同じ。変素名は何の値が代入されているかわかりやすい名前にする。2語以上の組み合わせる変数名にはアンダーバー_
を用いる。変数展開
文字列の中で
#{変数名}
とすることで変数を代入している値に置き換えて文字列を含めることを変数展開という。変数展開を行う場合は必ずダブルクオーテーション"
で囲む。シングルクォーテーションの場合、変数展開が行われず、そのまま文字列として扱われてしまう。また、数字と文字列は+
で文字連結できないので、そうゆう場合でも変数展開を用いる。index.rbname="田中" puts "名前は#{name}です" puts '名前は#{name}です'コンソール名前は田中です 名前は#{name}です
if文の書き方
処理は
if
とend
で囲む。C言語ではelse if
が使われるがRubyではelsif
を用いる。繰り返しの処理
each文を使う。
配列.each do |変数名|
と書き、end
までの間に実行したい処理を書く。index.rbnames=["田中","山本","山田"] names.each do |name| puts name endコンソール田中 山本 山田each文内の変数名(name)は好きな名前でいいが、配列の変数名(names)の単数形にすることが多い。
|変数|
はeach文のdoからendまでしか使えない。each文の外で定義した変数はeach文の中でも使うことができる。それぞれの変数の使用できる範囲をスコープという。ハッシュとは
複数の値を管理する方法の1つ。配列は複数の値を並べて管理するのに対して、ハッシュはそれぞれの値にキープという名前をつけて管理する。
index.rbuser={"name"=>"田中", "age"=>16} puts useruser={"name"=>"田中", "age"=>16} (↑定義したハッシュがそのまま出力される)ハッシュの要素を用いる
ハッシュの各要素の値は対応するキーを使って
ハッシュ[キー]
とすることで用いられる。また、ハッシュ[キー]=値
で更新できる。ハッシュ[新しいキー]=値
で追加することもできる。index.rbuser={"name"=>"田中", "age"=>16} puts user["name"] #キー"age"に対する値を更新 user["age"]=17 puts user #キー"gender"に対する値を追加 user["gender"]=male puts userコンソール田中 user={"name"=>"田中", "age"=>17} user={"name"=>"田中", "age"=>17, "gender"="male"}シンボル
ハッシュのキーの部分を文字列ではなく先頭にコロン
:
を付けた書き方。つまり、クォーテーションで囲む代わりに先頭にコロンをつける。クォーテーションで囲む場合と先頭にコロンをつける場合で出力結果は同じになる。文字列とシンボルは厳密には違うけど、基本的には同じように使える。
ハッシュのキー部分でシンボルを用いたらその値を用いるときはシンボルで指定しなければいけない。index.rbuser={"name"=>"田中", "age"=>17} puts user["name"] user={:name=>"田中", :age=>17} puts user[:name]【一般的】ハッシュのキーにシンボルを用いるときは省略して書くことができる。この書き方が一般的である。省略した場合でも、シンボルを用いて要素を取得する。
index.rbuser={name:"田中", age:17} puts user[:name]nilの扱い
ハッシュから存在しないキーの値を取り出したときの「何もない」という値のこと。読み方は「ニル」。putsしても何も表示されない。
index.rbuser={name:"田中", age:17} puts user[:height]要素がハッシュである配列
配列の要素にはハッシュを使うことができる。
配列[インデックス番号]
でハッシュを用いることができるので、そのハッシュを代入した変数を使って変数[キー]
でハッシュの要素の値を用いられる。index.rbusers=[ {name:"田中", age:17} {name:"山本", age:20} ] puts users[0] user=users[0] puts user[:name]コンソール{:name=>"田中", :age=>17} 田中上のを省略して書くことができる。
配列[インデックス番号][キー]
で特定のハッシュの値を用いることができる。index.rbusers=[ {name:"田中", age:17} {name:"山本", age:20} ] puts users[1][:name]コンソール山本each文を使って書くこともできる。
index.rbusers=[ {name:"田中", age:17} {name:"山本", age:20} ] users.each do |user| puts user end users.each do |user| puts user[:name] endコンソール{:name=>"田中", :age=>17} {:name=>"山本", :age=>20} 田中 山本