- 投稿日:2019-06-07T22:57:01+09:00
Railsチュートリアル3日目:1章クリア!
今日やったこと
・1章初めからやり直し
・1章クリア!初めからやり直したら、Gitの設定がうまくいった!
昨日はマージをしようとしたら、.c9/metadata...というファイルが邪魔をしてマージ出来ませんでした。.gitのファイル位置がおかしいことに気づき、今日はgit initする時のディレクトリに注意しながら、最初から1章をやり直してみました!
その結果、無事にマージすることが出来ました!
ec2-user:~/environment/hello_app (master) $ git branch * master modify-README ec2-user:~/environment/hello_app (master) $ git merge modify-README Updating f807c10..fd0d9f8 Fast-forward README.md | 9 +++++++++ 1 file changed, 9 insertions(+)その後は順調に進んで、1章をクリアすることができました!
(写真撮り損ねた…)ただ、また疑問が出てきて、cloud9を閉じてからもう一回herokuに入ろうとすると、
ec2-user:~/environment/hello_app (master) $ heroku --versionbash: heroku: command not foundあれ?herokuのバッシュが消えてる?
まだcloud9の仕様がわからず、一度閉じたら何がリセットされて何がそのままの設定で残っているのか、全然分かっていない気がします。
明日はこの辺りをググってみてcloud9やバッシュなど全体的に学んでいきたいと思いました。
- 投稿日:2019-06-07T21:01:37+09:00
rails モデルについて
modelの作成
$ rails g model モデル名上記をを実行するとマイグレーションファイルが作成される。
これを使うことでSQL文を書かずして、railsからmysqlなどのデータベースを操作することができる。作成するだけでは操作できない。マイグレーションファイルの実行
$ rails db:migrateこのコマンドでデータベースにモデル名のテーブルが作成される。
railsのルールとして一度実行されたファイルに変更をしてはならない。
データベースに変更を加えたい場合、rails db:migrate:resetでもう一度作り直すかカラムを追加する方法がある。カラムの追加
$ rails g migration Addカラム名Toテーブル名テーブル名はモデル名の小文字複数形ですが、上記ではキャメルケース記法なので大文字になります。
- 投稿日:2019-06-07T20:12:53+09:00
[error]rails aborted! I18n::MissingTranslationData: translation missing: en.faker.name.first_name
rails aborted!I18n::MissingTranslationData: translation missing: en.faker.name.first_name
bundle exec rails db:reset
しようとしたら、上記のエラーがでた解決方法
下記をコピペ*日本語での設定とかそこらへん
local.rbrequire 'i18n' I18n.locale # => :en I18n.locale = :ja I18n.locale # => :ja require 'faker' Faker::Config.locale # => :ja Faker::Internet.email # => ".@.com"で
$ bundle exec rails db:reset
- 投稿日:2019-06-07T20:12:53+09:00
[rails error]rails aborted! I18n::MissingTranslationData: translation missing: en.faker.name.first_name
rails aborted!I18n::MissingTranslationData: translation missing: en.faker.name.first_name
bundle exec rails db:reset
しようとしたら、上記のエラーがでた解決方法
下記をコピペ*日本語での設定とかそこらへん
local.rbrequire 'i18n' I18n.locale # => :en I18n.locale = :ja I18n.locale # => :ja require 'faker' Faker::Config.locale # => :ja Faker::Internet.email # => ".@.com"で
$ bundle exec rails db:reset
- 投稿日:2019-06-07T18:18:32+09:00
RailsでTwitterログイン認証を実装
RailsアプリでTwitterログインを実装する方法をまとめます。
deviseの導入
メールアドレスやSNSアカウントを用いてのログインを、簡単に実装するGem「devise」と、OAuth認証に必要なGem「omniauth」「omniauth-twitter」を導入します。
Gemfile.rbgem 'devise' gem 'omniauth' gem 'omniauth-twitter'続いて、bundle installを行います。
bundle install※ライブラリはサーバーの起動時に読み込まれるので、ここでいったんサーバーを停止し、再起動しましょう。
deviseの設定
アプリケーションにdeviseをインストールします。
rails g devise:install1から4までのステップが書かれた英文が表示されるので、指示通りにコーディングします。
デフォルトURL
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }をconfig/environments/development.rbに追加します。
config/environments/development.rbRails.application.configure do # Settings specified here will take precedence over those in config/application.rb. ・・・(略:場所はどこでも良いです) config.action_mailer.default_url_options = { host: 'localhost', port: 3000 } endroot_urlを指定
ルートURLにアクセスした際のページを作成します。
rails g controller Pages indexPagesコントローラーには、indexアクションを、ビューファイルindex.html.erbを追加しています。
フラッシュメッセージを指定
ログインが成功した際に表示する、フラッシュメッセージを、application.html.erbの
下に指定します。app/views/layouts/application.html.erb・・・(略) </head> <body> <p class="notice"><%= notice %></p> <p class="alert"><%= alert %></p> <%= yield %> </body>devise用のviewを作成
rails g devise:viewsapp/views/devise/以下にファイルが作成されます。
Userモデルを作成
rails g devise User※モデル名なので単数形
これにより、dbフォルダ下にマイグレーションファイルが作成されます。
ユーザーモデルを編集
user.rbのdevise:以下に「:omniauthable」を追加します。
model/user.rbdevise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable, :omniauthableデータベースにカラムを追加
deviseはデフォルトでメールアドレスとパスワードした扱うことができません。ツイッターログインで扱うデータのカラムをあらかじめ追加しておく必要があります。
以下のカラムを追加します。
- ユーザーID(uid)
- プロバイダー(provider)
- アカウント名(name)
- アカウントID(nickname)
- 場所(location)
- 画像(image)
rails g migration AddColumnsToUsers uid:string provider:string name:string nickname:string location:string image:stringここまで終わったら、以下マイグレーションを実行します。
rails db:migrateTwitter Developerの登録
API Keyと、Secret Keyを取得します。(省略)
取得した2つのキーを貼り付け
config/initializer/devise.rbDevise.setup do |config| ・・・(略) config.omniauth :twitter, 'API key(各自取得したキーを入れてください)', 'API secret(各自取得したキーを入れてください)' endUserモデルを編集する
model/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], image: auth.info.image, name: auth.info.name, nickname: auth.info.nickname, location: auth.info.location ) end user end private def self.dummy_email(auth) "#{auth.uid}-#{auth.provider}@example.com" end endTeitter認証の際に取得した各データを、データベースに格納しています。メールアドレスがない場合はdevise側でエラーが発生してしまうので、ダミーのアドレスを作成しています。
コールバックの設定
app/controllers/以下に「users」フォルダを作成し、その下に「omniauth_callbacks_controller.rb」ファイルを作成します。
omniauth_callbacks_controller.rbは以下のように編集します。
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? print("persisted true") flash[:notice] = I18n.t('devise.omniauth_callbacks.success', kind: provider.capitalize) sign_in_and_redirect @user, event: :authentication else print("persisted false") session["devise.#{provider}_data"] = request.env['omniauth.auth'] redirect_to controller: 'sessions', action: 'new' end end endルーティングの設定
config/route.rbのdevise_forを、以下のように編集します。
config/route.rbdevise_for :users, controllers: { omniauth_callbacks: 'users/omniauth_callbacks' }ビューファイルを整える
ビューファイルを以下のように整えます。
index.html.rb<% if user_signed_in? %> <%=current_user.email%> <%=current_user.name%> <%=current_user.nickname%> <%=current_user.image%> <%=current_user.location%> <%= link_to "ログアウト", destroy_user_session_path, method: :delete %> <% else %> <%= link_to "ログイン", new_user_session_path %> <%= link_to " Twitterでログイン/登録", user_twitter_omniauth_authorize_path %> <% end %>以上でツイッター認証ログインが可能になりました。
- 投稿日:2019-06-07T18:13:52+09:00
Ruby on Railsを開発する時にいれておきたいAtomのパッケージ
ファイル検索・移動系
Rails Transporter
Controller/Model/View間の移動をコマンド一つできる。
RubyMineにもそんな機能があったからAtomにもないかなと思って探したら発見。
ControllerからViewを探すのは結構めんどくさいからかなり重宝している。atom-fuzzy-grep
高速簡易グレップ。
Atomの標準でプロジェクト内全体の検索はできるが、このfuzzy-grepはより早く検索したい時におすすめ。
advanced-open-file
現在いるファイルから別のファイルを検索したい時に使える。
RailsだとViewでpartialの中身を確認したくて、別のファイルに移動する時に使える。
Viewって似たようなファイル名が多いから、grepしても検索結果が多くて判別できないため、これを使っている。goto-definition
関数定義場所のファイルにジャンプする。
私は
atom-fuzzy-grep
でも十分かなと思うが、直接関数に飛んでくれるのでたまに使う。Git系
git-blame
行毎に最終変更者が確認できる。
その名の通り、誰かのせいしたい時に使う。(笑)
git-time-machine
ファイルの過去の変更履歴を時系列で確認できる。
git-blameでは追えない犯人を追う時に使う。
その他
platformio-ide-terminal
Atom上にターミナルを開く。
初回起動の場所をプロジェクトのrootパス等に設定できるため、gitのコマンド等使いたい時に使用。
ちょっと重い。。(更新中。。)
- 投稿日:2019-06-07T17:44:23+09:00
cloud9→ローカルに移したら写真投稿ができなくなった
はじめに
SNS風の写真投稿アプリを久々にローカルで確認してみたところ、肝心の写真投稿がバリデーションに引っかかり、投稿はもちろん、テストなども通らなくなってしまっていました。
原因
結果を言ってしまうと、
Minimagick
を使うのに必要なImageMagick
を、ローカルでインストールしていませんでした。cloud9時代に
ImageMagick
をインストールした自体あまり覚えていなかったので、気付くのが遅れてしまいました。$ brew install imagemagickこれで今まで通り、問題なく写真投稿できるようになりました!
参考
Rails gem MiniMagick を利用して画像ファイルをリサイズする
RubyでImageMagick使うにはMiniMagickの方がよい
- 投稿日:2019-06-07T17:39:19+09:00
resize_to_limit(fit) 投稿されたメッセージをビューに表示させる際に、messageとimageが異常に大きい
今回の問題
chat-space/app/views/messages/_message.html.hamlに
.main-content__chat--contents .chat-message .chat-message--name = message.user.name .chat-message--time = message.created_at.strftime("%Y/%m/%d %H:%M") .chat-message--comment - if message.content.present? %p.lower-message__content = message.content = image_tag message.image.url, class: 'lower-message__image' if message.image.present?と記述し、ビューを表示させると、
imageも大きいが、messageもimageと同じ大きさで表示されてしまう。
やりたいゴール
ちょうどいい大きさで、messageのみの時は、それ相応の大きさにする
原因
app/assets/stylesheets/_groups.scssに高さを指定してしまっていた。
&__chat--contents{ background-color: #fafafa; height: 500px; padding: 10px 20px; overflow: scroll;heightをコメントアウトするとmessageのみの表示がちょうどいい大きさに変化した。
しかし画像が馬鹿でかすぎる
process resize_to_limit: [XXX, XXX]
resize_to_fitは縦横比を維持したまま、width, heightをXXXpxにリサイズしてくれる
app/uploaders/image_uploader.rbに
process resize_to_limit: [200, 200]を記述する
結果
ちょうどいい感じに表示されるようになりました!
- 投稿日:2019-06-07T15:37:58+09:00
Decorator
Decorator の使い方の備忘録です。
インストール
Gemfilegem 'active_decorator'Decoratorを生成
$ rails g decorator user
使い方
app/decocators/user_decorator.rbmodule UserDecorator def full_name "#{family_name} #{given_name}" end end参考
- 投稿日:2019-06-07T15:30:03+09:00
[Rails error]raise LoadError, "Unable to autoload constant #{qualified_name}, expected #{file_path} to define it" unless from_mod.const_defined?(const_name, false)
errpr!
raise LoadError, "Unable to autoload constant #{qualified_name}, expected #{file_path} to define it" unless from_mod.const_defined?(const_name, false)原因
controllerの名称間違いだった
tests_controller.rbTestController < ApplicationController def index end解決
上記の
TestController < ApplicationController
をTestsController < ApplicationController
に直したら治った
- 投稿日:2019-06-07T15:29:22+09:00
railsでhas_manyなmodelを条件付きで取ってるのをあらかじめ定義しておく
近況
転職してRailsマンに戻りました。(しばらくpythonおじさんだった)やりたいこと
has_manyしているテーブルをselectするとき、コントローラの中でfindとか書かずに予めmodelの中に定義しておきたい。
(見た目スッキリさせたいとか、変数当てる必要がないから定義済みにしといた方が安全とか色々理由はあると思う)どう書く?
lambdaを使うのが良いみたい。
app/models/user.rbclass User < ApplicationRecord # Userに紐づく予定を記録したSchedulesテーブルがあり、そこから稼働日に該当する予定だけを抜き出したい has_many :work_day, lambda { where not_work_day: True }, class_name: Schedules.name endコントローラからはこんな感じで書く。
app/models/user.rbdef work_day @result = User.find(id).includes(:work_day) end
- 投稿日:2019-06-07T14:15:15+09:00
ブラウザから S3 へダイレクトアップロード
はじめまして、streampackチームのminsuです。
やりたいこと
S3へファイルをアップロードする際に、Railsサーバを通すことなくブラウザからS3へのダイレクトアップロードを実装してみます。
ブラウザからS3にファイルを直接アップロードすることにより、余分な負荷を削減できるメリットがあります。
また、Railsのgem aws-sdkを利用して生成したpresigned POSTを利用することでブラウザにaws credentialsを持たせる事なくアップロードを行えます。AWSリソースの準備
まず、AWSアクセスキーを作成してACCESS_KEY_ID, SECRET_ACCESS_KEYを取得してください。
次にS3のバケットの作成します。
作成したバケットのCORSの設定を行い、外部からのPOSTを許可します。<?xml version="1.0" encoding="UTF-8"?> <CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> <CORSRule> <AllowedOrigin>*</AllowedOrigin> <AllowedMethod>GET</AllowedMethod> <AllowedMethod>PUT</AllowedMethod> <AllowedMethod>POST</AllowedMethod> <MaxAgeSeconds>3000</MaxAgeSeconds> <AllowedHeader>*</AllowedHeader> </CORSRule> </CORSConfiguration>AllowedOrigin、AllowedHeaderはワイルドカードを設定しましたが、環境に合わせて変更してください。
Railsでpresigned POSTを返すアクションを設定
まずは環境変数に必要な値を持たせておきます。
.envAWS_ACCESS_KEY_ID=your-key-id AWS_SECRET_ACCESS_KEY=your-secret-key BUCKET=your-bucket-name次にGemfileに
Gemfilegem `aws-sdk', '~3'を追加して
$ bundle installそして環境変数に保存した値を使ってS3のインスタンスを作成します。
config/initializers/aws.rbAws.config.update({ region: 'ap-northeast-1', credentials: Aws::Credentials.new(ENV['AWS_ACCESS_KEY_ID'], ENV['AWS_SECRET_ACCESS_KEY']), }) S3_BUCKET = Aws::S3::Resource.new.bucket(ENV['S3_BUCKET'])GET 要求に対して、 ブラウザから S3 へ POST するために必要な情報を返すアクションを実装します。
今回は video モデルのコントローラーにアクションを追加しました。VideosController < ApplicationController def upload filename = params[:filename] filetype = params[:filetype] post = S3_BUCKET.presigned_post( key: "upload_video/#{filename}", acl: 'public-read', content_type: filetype, metadata: { 'original-filename' => filename } }) render json: {url: post.url,fields: post.fields} end endバケット内の保存先は
key:
で指定するので、この値をDBに保存してモデルと紐づけることが可能です。GET リクエストで filename,filetype パラメータ受け取ったuploadアクションは以下のpresigned POSTとして次のjsonを返します。
{ "url": "https://your-bucket-name.s3.ap-northeast-1.amazonaws.com", "fields": { "key": "upload_video/test.mp4", "acl": "public-read", "Content-Type": "video/mp4", "x-amz-meta-original-filename": "test.mp4", "policy": "eyJleHBpc...", "x-amz-credential": "oiMjAxO...", "x-amz-algorithm": "AWS4-HMAC-SHA256", "x-amz-date": "20190607T004657Z", "x-amz-signature": "mF0aW9uIj..." } }ブラウザページの作成
動作としては
- RailsにGETリクエストを送ってpresigned POSTを受け取る
- presigned POSTを使ってS3へPOST
- 実装はfetch api
です
<!DOCTYPE html> <html> <head> <title>S3 POST Form</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> </head> <body> <input type="file" id="up_file"> <br><input type="button" id="send" onclick="upload();" value="アップロード"> <!-- fetch api --> <script> function upload(){ const up_files = document.getElementById('up_file'); const up_file = up_files.files[0]; if (up_files.value === "") { return false; } const url= 'http://localhost:3000/api/v1/video_upload/get_post_fields?filename=' + up_file.name + "&filetype=" + up_file.type; // Rails に GET console.log("GET 開始"); fetch( url, {method: 'GET'} ).then(response => { if(response.ok){ console.log("GET 成功"); return response.json(); } }).then((data)=>{ formdata = new FormData() for (key in data.fields) { formdata.append(key,data.fields[key]); } formdata.append("file",up_file); const headers = { "accept": "multipart/form-data" } // S3 に POST console.log("POST 開始"); fetch( data.url, { method: 'POST', headers, body: formdata } ).then((response) => { if(response.ok){ console.log("POST 成功"); return response.text(); } }) }); } </script> </body> </html>これでブラウザからのS3へのダイレクトアップロードを実装することができました。
参考
- 投稿日:2019-06-07T14:15:15+09:00
ブラウザからS3へのダイレクトアップロード
はじめまして、streampackチームのminsuです。
やりたいこと
S3へファイルをアップロードする際に、Railsサーバを通すことなくブラウザからS3へのダイレクトアップロードを実装してみます。
ブラウザからS3にファイルを直接アップロードすることにより、余分な負荷を削減できるメリットがあります。
また、Railsのgem aws-sdkを利用して生成したpresigned POSTを利用することでブラウザにaws credentialsを持たせる事なくアップロードを行えます。AWSリソースの準備
まず、AWSアクセスキーを作成してACCESS_KEY_ID, SECRET_ACCESS_KEYを取得してください。
次にS3のバケットの作成します。
作成したバケットのCORSの設定を行い、外部からのPOSTを許可します。<?xml version="1.0" encoding="UTF-8"?> <CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> <CORSRule> <AllowedOrigin>*</AllowedOrigin> <AllowedMethod>GET</AllowedMethod> <AllowedMethod>PUT</AllowedMethod> <AllowedMethod>POST</AllowedMethod> <MaxAgeSeconds>3000</MaxAgeSeconds> <AllowedHeader>*</AllowedHeader> </CORSRule> </CORSConfiguration>AllowedOrigin、AllowedHeaderはワイルドカードを設定しましたが、環境に合わせて変更してください。
Railsでpresigned POSTを返すアクションを設定
まずは環境変数に必要な値を持たせておきます。
.envAWS_ACCESS_KEY_ID=your-key-id AWS_SECRET_ACCESS_KEY=your-secret-key BUCKET=your-bucket-name次にGemfileに
Gemfilegem `aws-sdk', '~3'を追加して
$ bundle installそして環境変数に保存した値を使ってS3のインスタンスを作成します。
config/initializers/aws.rbAws.config.update({ region: 'ap-northeast-1', credentials: Aws::Credentials.new(ENV['AWS_ACCESS_KEY_ID'], ENV['AWS_SECRET_ACCESS_KEY']), }) S3_BUCKET = Aws::S3::Resource.new.bucket(ENV['S3_BUCKET'])GET 要求に対して、 ブラウザから S3 へ POST するために必要な情報を返すアクションを実装します。
今回は video モデルのコントローラーにアクションを追加しました。VideosController < ApplicationController def upload filename = params[:filename] filetype = params[:filetype] post = S3_BUCKET.presigned_post( key: "upload_video/#{filename}", acl: 'public-read', content_type: filetype, metadata: { 'original-filename' => filename } }) render json: {url: post.url,fields: post.fields} end endバケット内の保存先は
key:
で指定するので、この値をDBに保存してモデルと紐づけることが可能です。GET リクエストで filename,filetype パラメータ受け取ったuploadアクションは以下のpresigned POSTとして次のjsonを返します。
{ "url": "https://your-bucket-name.s3.ap-northeast-1.amazonaws.com", "fields": { "key": "upload_video/test.mp4", "acl": "public-read", "Content-Type": "video/mp4", "x-amz-meta-original-filename": "test.mp4", "policy": "eyJleHBpc...", "x-amz-credential": "oiMjAxO...", "x-amz-algorithm": "AWS4-HMAC-SHA256", "x-amz-date": "20190607T004657Z", "x-amz-signature": "mF0aW9uIj..." } }ブラウザページの作成
動作としては
- RailsにGETリクエストを送ってpresigned POSTを受け取る
- presigned POSTを使ってS3へPOST
- 実装はfetch api
です
<!DOCTYPE html> <html> <head> <title>S3 POST Form</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> </head> <body> <input type="file" id="up_file"> <br><input type="button" id="send" onclick="upload();" value="アップロード"> <!-- fetch api --> <script> function upload(){ const up_files = document.getElementById('up_file'); const up_file = up_files.files[0]; if (up_files.value === "") { return false; } const url= 'http://localhost:3000/api/v1/video_upload/get_post_fields?filename=' + up_file.name + "&filetype=" + up_file.type; // Rails に GET console.log("GET 開始"); fetch( url, {method: 'GET'} ).then(response => { if(response.ok){ console.log("GET 成功"); return response.json(); } }).then((data)=>{ formdata = new FormData() for (key in data.fields) { formdata.append(key,data.fields[key]); } formdata.append("file",up_file); const headers = { "accept": "multipart/form-data" } // S3 に POST console.log("POST 開始"); fetch( data.url, { method: 'POST', headers, body: formdata } ).then((response) => { if(response.ok){ console.log("POST 成功"); return response.text(); } }) }); } </script> </body> </html>これでブラウザからのS3へのダイレクトアップロードを実装することができました。
参考
- 投稿日:2019-06-07T09:14:41+09:00
ActiveRecordのinclude、joins、eager_load、preloadの表まとめ
表題の件について完全に自分用の備忘録としてまとめる
メソッド JOIN associationのキャッシュ クエリ数 その他 joins LEFT JOIN × 1 JOINしたテーブルで絞込ができる。 eager_load LEFT OUTER JOIN ○ 1 JOINしたテーブルで絞込ができる。 preload - ○ 複数 preloadしたテーブルによって絞り込もうとすると、例外を投げる。 includes - - - eager_load か preloadの動きをする それぞれ使いどころがあると思うが、個人的には使っていてeager_loadが全体的に一番使いやすいのではと思う。
- 投稿日:2019-06-07T09:01:53+09:00
【Rails】バッテリーホイミ機能を実装しました
個人開発のWebアプリ「まちかどルート」v6.1に、名づけて《バッテリーホイミ機能》なるものを実装したときのメモです。
TL; DR
まちかどルートは
「道ばたのゴミを拾おう」
「お年寄りに席をゆずろう」
「〇〇に行って〇〇しよう」 など。みんなの日常からちょっとした一日一善やおつかいなどをお題にしてサブクエストを作りクリアしあうことで世界がちょっと明るくなる、そんなリアルRPG系Webアプリです。
そしてユーザーには、レベルや経験値のほかHP (ヒットポイント:ドラクエのアレ)という属性値を持たせています。
Battery Status API
どうやらPCとAndroidのChrome限定のようですが、バッテリーの状態変化でJavaScriptを発火させることのできるBattery Status APIというものがあります。
今回はそれを応用してみました。
こんな流れです。
1. まちかどルートを開く
2. 充電を始める
3. APIが充電を検知したことを画面に表示
4. バッテリー残量値を取得
5. 「ホイミ!」ボタンを押す
6. バッテリー残量値をHPに加算してDBに保存view / JavaScript
index.html.erb<div id="posts"> # ここに下記のJavaScriptからDOM要素が挿入されます </div>application.jsnavigator.getBattery().then(function(battery) { // 充電を検知したら発火 battery.onchargingchange = function(){ // 充電開始(true)のときだけ処理 if (battery.charging === true) { // viewのid="posts"のところにDOM要素を挿入 var element = document.getElementById("posts"); element.insertAdjacentHTML("afterbegin", " <p>充電を検知</p> <form action='battery' accept-charset='UTF-8' method='get'> <input name='utf8' type='hidden' value='✓'> <input type='text' id='battery' name='battery' readonly=''> </input> <button name='button' id='battery_btn' type='submit' disabled> ホイミ! </button> </form> "); } } // 充電の残量が変化したら発火 battery.onlevelchange = function(){ // 充電の残量値を入力フォームに表示 document.getElementById( "battery" ).value = battery.level * 100; // 入力フォームのdisabledを無効にして「ホイミ!」ボタンを押せるようにする document.getElementById( "battery_btn" ).disabled = ""; } });controllerでホイミ!
posts_controller.rbdef battery # viewから送られてきたバッテリー残量値をHPに加算してDB保存 if params[:battery] != nil battery = params[:battery] @current_user.hp += battery.to_i @current_user.save flash[:notice] = "HPが回復しました!" redirect_to root_path else flash[:error] = "呪文が失敗しました!" redirect_to root_path end endルーティング
config\routes.rbget 'battery' , as: 'battery', to: 'posts#battery'あとがき
とてもザックリな感じになってしまいましたが、要点は上記のとおりです。HPが残り少なくなったらバッテリーを充電して「ホイミ!」
けっこう楽しいです。
オープンソース開発用のリポジトリを公開しました。今回の件、こちらにもアップしてあります。
https://github.com/west2538/machiroute_oss
- 投稿日:2019-06-07T02:04:44+09:00
rails s -b 0.0.0.0の意味
rails s: rails serverの略、サーバーを立ち上げるコマンド
-b 0.0.0.0: 立ち上げたサーバーを0.0.0.0にバインドする
→ 0.0.0.0は特別な値、マシンがもっているipアドレス全てに対してバインドすることになる。この記事がわかりやすい。
https://keens.github.io/blog/2016/02/24/bind_addressnoimigayouyakuwakatta/
- 投稿日:2019-06-07T01:53:42+09:00
Rspecで変更が無い事を確認しようとしたらLint/AmbiguousBlockAssociationというLintエラーが発生した
テスト自体は通っていたが、プルリクを出す前にRuboCopを動かして検証したところ、Lint/AmbiguousBlockAssociationという以下のLintエラーが発生した。
Lint/AmbiguousBlockAssociation: Parenthesize the param change{ analysis.foo_count } to make sure that the block will be associated with the change method call.
該当のspecファイルの記述抜粋(一部、実態のコードから変更させてる部分があります)require 'rails_helper' RSpec.describe Dummy, type: :model do describe '.method' do subject { Dummy.method!(foo_analysis: analysis, foo_data: foo_data) } let(:analysis) { create :users_foo_analysis } context 'when foo_data is empty' do let(:foo_data) { [].to_json } it { is_expected.to eq Dummy.none } it { expect { subject }.to_not change{ analysis.foo_count } } end動作しない前提で、試しに以下のように変更をかけてテストを動作させてみた。
変更前■変更箇所 it { expect { subject }.to_not change{ analysis.foo_count } }変更後it { expect { subject }.to_not change analysis.foo_count }すると、以下のようなエラーが表示された。
ArgumentError: `change` requires either an object and message (`change(obj, :msg)`) or a block (`change { }`). You passed an object but no message.(
change { }
)の形式ではRuboCopに怒られてしまっていたので、(change(obj, :msg)
)の形式に修正した形でテストを通しつつ、RuboCopに怒られないようにするためにどうすれば良いか調査してみた。結論、以下のような記述であれば、テストを通しつつ、RuboCopに怒られずにすんだ。
最終形it { expect { subject }.to_not change{analysis, :foo_count) }
change(obj, :msg)
の:msgって何だろう?と戸惑ったが、普通にメソッドを渡せば動きそうだなと思い、試しにやってみたら上手くいった。:msgとかではなく、もっと分かりやすいエラーメッセージなら素早く解決できたのに。。。。
- 投稿日:2019-06-07T01:53:42+09:00
RSpecで変更が無い事を確認しようとしたらLint/AmbiguousBlockAssociationというLintエラーが発生した
テスト自体は通っていたが、プルリクを出す前にRuboCopを動かして検証したところ、Lint/AmbiguousBlockAssociationという以下のLintエラーが発生した。
Lint/AmbiguousBlockAssociation: Parenthesize the param change{ analysis.foo_count } to make sure that the block will be associated with the change method call.
該当のspecファイルの記述抜粋(一部、実態のコードから変更)require 'rails_helper' RSpec.describe Dummy, type: :model do describe '.method' do subject { Dummy.method!(foo_analysis: analysis, foo_data: foo_data) } let(:analysis) { create :users_foo_analysis } context 'when foo_data is empty' do let(:foo_data) { [].to_json } it { is_expected.to eq Dummy.none } it { expect { subject }.to_not change{ analysis.foo_count } } end動作しない前提で、試しに以下のように変更をかけてテストを動作させてみた。
変更前■変更箇所 it { expect { subject }.to_not change{ analysis.foo_count } }変更後it { expect { subject }.to_not change analysis.foo_count }すると、以下のようなエラーが表示された。
ArgumentError: `change` requires either an object and message (`change(obj, :msg)`) or a block (`change { }`). You passed an object but no message.(
change { }
)の形式ではRuboCopに怒られてしまっていたので、(change(obj, :msg)
)の形式に修正した形でテストを通しつつ、RuboCopに怒られないようにするためにどうすれば良いか調査してみた。結論、以下のような記述であれば、テストを通しつつ、RuboCopに怒られずにすんだ。
最終形it { expect { subject }.to_not change{analysis, :foo_count) }
change(obj, :msg)
の:msgって何だろう?と戸惑ったが、普通にメソッドを渡せば動きそうだなと思い、試しにやってみたら上手くいった。:msgとかではなく、もっと分かりやすいエラーメッセージなら素早く解決できたのに。。。。
- 投稿日:2019-06-07T01:46:20+09:00
コントローラに書くコードを意識する
自分がエンジニアバイトをしているところでは週1回Rails勉強会をしています。今回はそのやったところのまとめを残しておきます。
参考書:現場で使える Ruby on Rails 5速習実践ガイドコードを書く場所を意識する
アプリケーションを作る上で何のコードをどこに書くかはとても重要になってきます。開発が進むにつれ、様々な機能を実装するためコードの量が増え複雑になっていきます。そこで少ないコストで全体を把握するには「 コードを書く場所を意識する」ことが重要になってきます。
コントローラに書くべきコード
RailではMVCを採用しています。それぞれに役割を持たせることで、どこが何をするところなのかを分けて管理しやすくしています。その中でコントローラの役割は送られてきたリクエストに対して、適切なレスポンスを返すのが仕事です。適切なレスポンスを返すためにModelやViewに対して働きかけます。
def index @user = User.all end開発初期の頃は上記のようにとてもシンプルなコントローラですが、開発が進むとModelに書くべきビジネスロジックが増え、どんどん複雑さが増してしまうことが多くなります。そのためコントローラはModelから値を取り出したり、保存したりする計算処理(ビジネスロジック)をあくまで呼び出す処理に集中する必要があります。
検索条件を書いたコード
User.where(name: "Bob")のように(短いですが)DBから検索をかけるようなコードの場合、コントローラに書くのではなく,Modelにscopeとして書く必要があります。
オブジェクトのデータを変更させるようなコード
@user.name = "Tom"上記のようなオブジェクトがもつデータの変更がおきているコードの呼び出しが多数ある場合、その部分はModelに移したほうがよいでしょう。例えば、「ユーザーの情報を変更するメソッド」のような統合的なメソッドをModelに作り、コントローラ側で呼び出すだけにするとコントローラはスッキリしたものになります。