- 投稿日:2019-03-07T23:49:27+09:00
Railsで新しいプロジェクトを始めた時に必ずやっておきたい2つの設定
こんにちは、とくめいチャットサービス「ネコチャ」運営者のアカネヤ(@ToshioAkaneya)です。
今回はRailsで新しいプロジェクトを始めた時にやっておきたい2つの設定を紹介します。
重要ですので、必ずやっておきましょう。Railsで新しいプロジェクトを始めた時にやっておきたい2つの設定
turbolinksを無効化する
詳しくはこちらの記事で解説していますのでご覧下さい。
Railsでページ遷移後にJavaScriptが実行されない問題の解消法
これを行わないと、JavaScriptが思うように動作しないことがあります。rails consoleが動くようにする
$ rails consoleはとても重要なコマンドですが、最近のバージョンではエラーが発生してしまうことがあります。Gemfilegroup :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] gem 'rb-readline' endGemfileに
gem 'rb-readline'を追加して、$ bundleを実行して下さい。以上です。
はてなブックマーク・Pocketはこちらから
- 投稿日:2019-03-07T21:02:40+09:00
【Rails】boolean型のカラムのバリデーション方法
- 投稿日:2019-03-07T18:29:59+09:00
プログラミング学習 記録 Railsチュートリアル11,12章
11、12章終わりました
学習時間は4時間程。一周目なので完全に理解できていない。
11章
- アカウントの有効化
- Userモデルに有効化トークンや有効化ステータスを付与する
- ユーザー登録
- ユーザー認証
- アカウント有効化のメールを送信
覚えたこと
どうやらActivartionトークンが必要らしい
既存のユーザーモデルにアカウント有効化のコードを追加
class User < ApplicationRecord
attr_accessor :remember_token, :activation_token
before_save :downcase_email
before_create :create_activation_digest
validates :name, presence: true, length: { maximum: 50 }
メソッドも# メールアドレスをすべて小文字にする def downcase_email self.email = email.downcase end # 有効化トークンとダイジェストを作成および代入する def create_activation_digest self.activation_token = User.new_token self.activation_digest = User.digest(activation_token) endそしてテストの準備としてサンプルユーザーを最初から有効にしておく
seed.rbにactivated: true, acivated_at: Time.zone.nowを追記アカウント有効化のメール送信
送信する為にはAction MailerというライブラリをUserのメイラーに追加するらしい
Userメイラーの生成をしてrails generate mailer UserMailer account_activation password_reset
作られたtextbビューとhtmlビューに表示する内容を書いていく
ちなみに生成されたメイラーのレイアウトはapp/views/layoutsで確認できる
あとはuser_mailer.rbでアカウント有効化リンクを定義して、developmentで試して終了
authenticated?メソッド等重要な点もあるがあくまで記録なので省略
production環境でも出来るらしいが2周目に回します
- 投稿日:2019-03-07T18:00:17+09:00
RailsでのSEOに関してのメモ
SEOとは
SEO(Search Engine Optimization)とは検索エンジン最適化または検索エンジン最適化ツールのことである。Googleなどの検索エンジンの検索結果の上位に自分のサイトを出したいときにこのSEO対策はすると良い。
SEO対策はなぜ必要か
Googleなどの検索エンジンにて検索を行った際に、検索結果の上位に自分で作成したものを持ってきて、より多くの人に見てもらうため。良い記事、良いサービスであったとしても検索結果の上位に出てこなかった場合にはユーザーに閲覧してもらえない。Internet Marketing Ninjasの行った調査によると、検索結果の一番上に出てくるサイトは21.1%のクリック率で、2番目に出てくる検索結果は、10.65%、4番目以下は5%を下回る。このことからもわかるように閲覧(クリック)されるためには検索結果の上位に自分のサイトが表示されなければならない。
対象とする読者
Railsでの開発を行っていて、SEO対策に関して初心者の人
対策として行うべきこと
- Sitemapの登録
- meta tagsの設置
- Canonicalの設置
- Page speed
- CSS, JavaScriptの最適化
- 画像の圧縮(主にモバイル用)
Sitemapについて
sitemapを登録するときにはRailsではsitemap_generatorとwheneverを用いる
- sitemapを生成するときにはconfig/sitemap.rbの中にsitemapとして追加したいものをaddを使って記述していく
- 重要なのはsitemapを生成するときには
rails routesで調べるんじゃなくて、ページベース(つまりは、実際にユーザーが検索でアクセスしたいと思われるページ)で追加していく- 管理者のページとかだと追加しないのが好ましい
meta-tagsについて
使うツール
- facebookのdebugger
- twitterのdebugger
- chromeのinspector(headタグ内を調べる)
- 参考としてchromeの拡張機能のlighthouse
チェックする項目
- title(lighthouseで確認可能)
- meta description(lighthouseで確認可能)
- canonical
Meta descriptionについて
Meta descriptionとは
ページ内の概要を表すテキスト情報。検索結果にサマリーとして表示される。ただSEO上の効果はほぼない
Canonicalについて
Canonicalとは
ページ内容が類似もしくは重複しているURLが複数存在する場合に、検索エンジンからのページが評価が分散されないよう、正規のURLがどれなのかを検索エンジンに示すために用いる記述
同じページなのに別ページとみなされるURLの例
index.htmlの場合
URL末尾の/のありなし
上記のようにちょっとした違いでも検索エンジンに別ページとしてみなされるので、SEOの順位を上げるためにはcanonical(正規)を設定することが必要
railsだとmeta-tagで、定義することが可能である
ページの読み込み順について
Page speedについて
Webサイトの表示速度を早くするためにやることとしては主に3個ある
- 表示する画像の圧縮
- CSS, JavaScriptの最適化をする
- ブラウザのキャッシュを利用する
使うツール
表示する画像の圧縮について
表示する画像の大きさによって、レスポンスとして送る情報量が変わり、それは表示スピードにも影響する。なので、画像の圧縮は必要である
対策
- 拡張子がpngのものを用いたほうが圧縮率が高くなるので良い
- spriteなどを用いて複数の画像をまとめて送信する
具体的には以下のリンクを参考にすると良い
画像ファイルの最適化とスプライト画像の作り方CSS, JavaScriptの最適について
ページを描画する際には、まずブラウザはHTMLからDOMを作成してそれを元に随時読み込まれた情報を描画していく。基本的にはHTMLファイルの上から順番に描画を行っていく。ページスピードとして測られるのはHTMLの描画についてなので、なるべく早くこの描画を終わらせることが表示速度を上げることにつながる
対策
- ユーザーが最初に目に触れる箇所(例えば下に長く続いているページであれば、ページの上の部分だけ)を最初にスタイルが当たるようにする。具体的には、stylesheet link rel = "ほにゃらら"のように外部のCSSファイルを読み出すのではなく、HTMLのmeta headの中に最初に目に触れそうだと思われる部分のCSSだけ書いておく
- headタグの中にstyle sheetやjsの記述を書いてしまったら、それを読み込み終わるまでHTMLのbody部分の描画が行われないのでこれを避けるために、JavaScriptとCSSの読み込みを
</body>の一個前の行に書く。具体的にはこれを行うためには少し変わった処理(JavaScriptでCSSを読み込む手法)が必要である。JavaScriptでCSSを読み込む手法
<noscript id="deferred-styles"> <%= stylesheet_link_tag "スタイルシート名前" %> </noscript> <script> var loadDeferredStyles = function() { var addStylesNode = document.getElementById("deferred-styles"); var replacement = document.createElement("div"); replacement.innerHTML = addStylesNode.textContent; document.body.appendChild(replacement) addStylesNode.parentElement.removeChild(addStylesNode); }; var raf = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; if (raf) raf(function() { window.setTimeout(loadDeferredStyles, 0); }); else window.addEventListener('load', loadDeferredStyles); </script> </body>上のプログラムのような感じでJavaScriptを読み込むようにするのが良いと現状では言われている。
参考・引用
- 投稿日:2019-03-07T17:02:46+09:00
Rubyで使用する各ツールの用途について
Rubyで活躍する代表的なツール
まずはツールの名前だけ先に上げていくことにします。
詳しくは以下でまとめていきますので一緒に確認していきましょう!・Gem
・Ruby On Rails(gemの中の1つ)
・bundler
・sequel proGemとは
Gemはライブラリの一種です。
Gemはどういった用途があるかというと、例えばとある機能を実装しようとした時に自分で1から実装しようとすると、かなりの労力と時間がかかってしまう可能性があるのですが、Gemではすでに他の誰かが開発済みの機能を借りて来ることができてしまうんです。つまり、アプリ作成において自分で実装する部分を最小限に抑えることができるというかなりの優れものです。
Gemについての詳細はこちらを参考にしてみてください!
https://blog.codecamp.jp/rails-gemSequelproとは
次にSequelproについてですがこちらはGUIツールとよばれるものの1つです。
簡単にいうと、データベースにつなげるためのものです。
データベース(DB)はMySQLというものがよく知られています。MySQLへの接続方法の詳細についてはこちらを参考にしてみてください!
https://qiita.com/iwaseasahi/items/e245e61da4b7613494c5bundlerとは
bundlerとはGem同士の互換性を保ちながら、パッケージの種類やバージョンを管理してくれる仕組みを持つものです。
実はbundlerもGemの1つです。
このbundlerがないと以下のようなことが起きてしまい、動作がうまくいかない現象が多発してしまいます。例えば、いくつもライブラリを使用している中でAのライブラリは最新の状態で保持されているが、ライブラリBは1つ前のバージョンであった場合に互換性の問題でうまく動作しない。
こういった現象が起きないように管理してくれるのがbundlerというわけです。
bundlerをインストールしておくだけで無意識にこういったことが原因で起きるエラーを回避できるということなんです。インストールしておいて損はないので是非インストールしましょう!
インストールについては以下を参考にしてください!
- 投稿日:2019-03-07T15:40:32+09:00
Rails開発で最低限気をつけること(=気をつけてほしいこと)
概要
Rails開発で最低限気をつけること(=気をつけてほしいこと)をメモ
少し長いですがRailsを覚え始めの人に読んでいただければと。全般
タイポをしない
当たり前ですが、タイポの原因はタイピングをミスすることです
残念ながらrubyは動的型付け言語であり、タイポによるエラーはプログラム実行時に発生します
タイポを防ぐ方法として、
- Lintを活用する
- 変数はコピペする
- スペルが間違っていないか辞書 or Google で検索するようにする
などが挙げられます
上記を徹底し、 視覚的にタイポを防ぐ 、 タイピングをやめる ことでタイポ0を目指しましょうインデントを揃える
PullRequestを作成する前には、必ずコードのフォーマットを直しましょう
インデントが揃っていることはソフトウェアエンジニアのマナーの一つだと思いますString vs Symbol
Sybmolの方がパフォーマンスが良いため、できるだけStringではなくSymbolを使うようにしてください
理由は下記の記事を参考ください
Rubyの文字列とシンボルの違いをキッチリ説明できる人になりたい - Qiita
ifvsif notvsunlessrubyでは条件式の判定に、
ifif notunlessなどがあります
条件式が複雑かつ、否定演算子などが組み合わされると一気に可読性が低下し、バグの原因につながるため、
条件式では「常に正常系を」書くようにしています
いくつか例を挙げてみます例:
if ~ else構文if @record.save # 条件式は正常系 # 成功時の処理を書く else # 失敗時の処理を書く end例
unlessでGurad構文(=早期リターン)def process(record) return false unless record.valid? # 早期リターン(=条件式は正常系) # 以下、正常系の処理を実行 end「常に正常系を」を記述することのを推奨する理由については下記リンクを参考にしてみてください
ifとunlessの使い分けboolean型のメソッド名には末尾に
?をつける一般的に、rubyではbooleanを返すメソッドには末尾に
?をつける習慣があります
メソッド名の末尾に?がついていることで boolean を返すことがわかり可読性が上がりますぼっち演算子
&.をつけるrubyでは、2.3から
&.演算子(safe navigation operator = ぼっち演算子)が導入されました
実行時に nil なオブジェクトに対してメソッドチェーンを実行するとundifined method error for nil:NilClassと
なってしまうため、nilになる可能性のあるメソッドチェーン呼び出しには全て&.をつけるようにすべきですソースコードの責任の範囲を意識する
OOPの思想に沿って、ソースコードの責任の範囲を考えて設計&実装する
Rails開発はMVCに依存しがちになますが、もっと柔軟にクラスを切った方が良いと思います
また、アプリケーションやビジネスロジックに依存せず汎用的に使えるクラスはlib配下に記述することもおすすめします例として、下記のようにディレクトリを切ると良いかなと思います
- app - controllers - decorators - forms # form経由の値を扱う(Controllerをファットにさせない) - helpers - jobs - listeners # wisperなど、Observerパターンでcallbackを処理する - mailers - models - operators # ビジネスロジックを扱う(ControllerやModelをファットにさせない) - policies # punditなどで権限管理 - validators # 独自定義したバリデーション - values # Valueオブジェクト - lib - xxx - xxx - xxxController
before_actionでインスタンス変数への代入を控える
before_actionを複数記述した場合、記述した順番に実行されます
before_action内で、他のbefore_actionで代入された変数を呼び出すと、
プログラムが正しく動作するかどうかがbefore_actionを呼び出す順番に依存してしまい、
スパゲッティコードにつながってしまいます
可能であれば変数を取得できるメソッドを作成することをおすすめします×
before_actionを使うclass UsersController < ActionController::Base before_action :set_user, only: [:show] def show end def set_user @user = User.find(params[:id]) end end◯ 専用のメソッドを用意する
class UsersController < ActionController::Base def show end def user @user = User.find(params[:id]) end helper_method: user end
helper_method :userとすることで、viewファイルでも変数を参照できるようになりますインスタンス変数をメモ化する
ActiveRecord経由で取得するデータは、変数をメモ化することで値のキャッシュができます
展開された変数はリクエスト終了時にクリアされるため、可能な限りキャッシュすることをおすすめしますclass UsersController < ActionController::Base def show end def user # @note @user がnilの場合のみ代入され、nilでなければキャッシュされたデータを返す @user ||= User.find(params[:id]) end helper_method: user endレコードの保存処理を行う場合は
flashを表示するレコードの保存処理を行う場合は成功時&失敗時に合わせて適切なflashメッセージを表示するようにしてください
def create if @record.save redirect_to records_path flash[:success] = 'レコードの保存に成功しました' else render :new flash.now[:error] = 'レコードの保存に失敗しました' end end def destroy if @record.destroy redirect_to records_path, flash: { success: 'レコードを削除しました' } else redirect_to records_path, flash: { error: 'レコードを削除できませんでした' } end endまた、レコードの更新に失敗し
renderを実行する場合はflash.nowを使うようにしてください
参考: 【Rails】flashとflash.nowの違い - avosalmonのブログModel
belongs_toにはrequired: trueまたはpresence: trueをつける
belongs_toで必ず親となるレコードが存在する場合は、required: trueまたはpresence: trueを記述してください
has_one,has_manyにはclass_nameをつける
has_oneまたはhas_manyを使う場合は、class_nameオプションをつけることで、
モデルが取得できずエラーとなってしまうことを防ぐことができる場合があるため、記述するようにするべきです
必要に応じてforeign_keyも指定することをおすすめします
has_one,has_manyにはdependentオプションをつける削除時に
has_oneまたはhas_many先の子モデルに対する振る舞いをdependentオプションで定義できます
不要なレコードはDBのパフォーマンスにも影響が出るので、適切に設定することをおすすめします
dependentオプションについては、下記リンクで詳しく説明されていたので参照してみてくださいActiveRecord::has_manyのdependentオプション
バリデーションを記述する
DB層でのバリデーションが必要なカラムに対しては、
validatesメソッド等を使って
適宜バリデーションを記述する
また、必要に応じて適宜カスタムバリデーションを作成して再利用できるようにすることもおすすめします
カスタムバリデーションを実行するView
form_withを使うRails5.1からは
form_forとform_tagがform_withというインターフェースに統合され、
URLベース、スコープ、モデルを指定してformタグを生成できるようになりました※
form_forを使う場合はlocal: trueを設定してください
https://qiita.com/bluegirl_beer/items/a361171f653edcd888ad
form_forやform_withではモデルの指定でaction先を絞るrailsで自動生成されるpathって読みづらいですよね
form_forやform_withでは、渡すオブジェクトが保存されているかどうかで
createのアクションを実行するか、updateのアクションを実行するかを自動的に判別してくれます
また、必要に応じてmethodやactionオプションを渡すことで、アクション先を絞ることができますDB
migrationファイルでカラムを追加するときは
commentをつける
commentオプションをつけることで、生成されるスキーマファイルにコメントを追加できます
可能な限りコメントの追加をお願いしますclass CreateBlogs < ActiveRecord::Migration[5.1] def change create_table :blogs, comment: 'ブログ' do |t| t.string :title, comment: 'タイトル' t.text :body, comment: '本文' t.timestamps t.datetime :deleted_at end end end
- 投稿日:2019-03-07T14:30:42+09:00
heroku run rails db:migrateのエラー発生時の解決法
初投稿です。
Railsチュートリアル等でもよく見るエラーなので、メモとして残しておきます。環境
・cloud9
herokuを走らせようとしたらエラーが出た
cloud9上で
$ heroku run rails db:migrateと入力すると
$ heroku run rails db:migrate WARNING WARNING Node version must be >=8.0.0 to use this CLI WARNING Current node version: 6.15.0 WARNING /home/ec2-user/.nvm/versions/node/v6.15.0/lib/node_modules/heroku-cli/node_modules/@oclif/command/lib/command.js:28 async _run() { ^^^^「今バージョン6.15.0だけど8.0.0に上げてね」ということらしい。
1、node.jsアップデート
こちらを参照してversionを上げてく。
①今のversion確認
$ node --version v6.15.0②v8.0.0にアップデート
$ nvm install v8.0.0 v8.0.0 is already installed. Now using node v8.0.0 (npm v5.0.0)③今のversion確認
$ node --version v8.0.0アップデート成功。
④再度走らせてみる
$ heroku run rails db:migrate module.js:487 throw err; ^ Error: Cannot find module 'typescript' at Function.Module._resolveFilename (module.js:485:15) at Function.Module._load (module.js:437:25) at Module.require (module.js:513:17) at require (internal/module.js:11:18) at Object.<anonymous> (/home/ec2-user/.nvm/versions/node/v8.0.0/lib/node_modules/heroku-cli/node_modules/@oclif/config/lib/ts-node.js:5:22) at Module._compile (module.js:569:30) at Object.Module._extensions..js (module.js:580:10) at Module.load (module.js:503:32) at tryModuleLoad (module.js:466:12) at Function.Module._load (module.js:458:3)違う問題が発生…
2、moduleを入れる
上から4行目に
Error: Cannot find module 'typescript'とあるので、こちらを参照。
⑤足りないmoduleを入れてみる。
$ npm install -g npm-install-missing /home/ec2-user/.nvm/versions/node/v8.0.0/bin/npm-install-missing -> /home/ec2-user/.nvm/versions/node/v8.0.0/lib/node_modules/npm-install-missing/bin/npm-install-missing added 2 packages, removed 2 packages and updated 12 packages in 10.625s ╭─────────────────────────────────────╮ │ │ │ Update available 5.0.0 → 6.9.0 │ │ Run npm i -g npm to update │ │ │ ╰─────────────────────────────────────╯ bash: ource: command not found$ npm-install-missing npm-install-missing: No modules seem to be missing. Huzzah!できた?
⑥再度実行
$ heroku run rails db:migrate module.js:487 throw err; ^ Error: Cannot find module 'typescript' at Function.Module._resolveFilename (module.js:485:15) at Function.Module._load (module.js:437:25) at Module.require (module.js:513:17) at require (internal/module.js:11:18) at Object.<anonymous> (/home/ec2-user/.nvm/versions/node/v8.0.0/lib/node_modules/heroku-cli/node_modules/@oclif/config/lib/ts-node.js:5:22) at Module._compile (module.js:569:30) at Object.Module._extensions..js (module.js:580:10) at Module.load (module.js:503:32) at tryModuleLoad (module.js:466:12) at Function.Module._load (module.js:458:3)うーん、変わらず…
3、npm install
その後heroku loginやheroku -v等をしても同じエラーが出て断念。
過去に僕が書いたこちら(teratail)を参考に色々実行してみる。⑦$ npm install
$ npm install npm notice created a lockfile as package-lock.json. You should commit this file. up to date in 0.098s⑧$ npm install -g heroku-cli
$ npm install -g heroku-cli npm WARN deprecated heroku-cli@7.0.9: 'heroku-cli' has been renamed 'heroku' npm WARN deprecated cross-spawn-async@2.2.5: cross-spawn no longer requires a build toolchain, use it instead /home/ec2-user/.nvm/versions/node/v8.0.0/bin/heroku -> /home/ec2-user/.nvm/versions/node/v8.0.0/lib/node_modules/heroku-cli/bin/run added 1 package and updated 14 packages in 26.604s⑨$ heroku run rails db:migrate
$ heroku run rails db:migrate › Warning: heroku-cli update available from 7.0.9 to 7.22.2. Running rails db:migrate on ⬢ hukumiru... up, run.9955 (Free) D, [2019-03-07T04:59:18.403914 #4] DEBUG -- : (65.5ms) CREATE TABLE "schema_migrations" ("version" character varying NOT NULL PRIMARY KEY) D, [2019-03-07T04:59:18.417964 #4] DEBUG -- : (10.8ms) CREATE TABLE "ar_internal_metadata" ("key" character varying NOT NULL PRIMARY KEY, "value" character varying, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL) D, [2019-03-07T04:59:18.420152 #4] DEBUG -- : (0.9ms) SELECT pg_try_advisory_lock(4540128404952329490) D, [2019-03-07T04:59:18.449576 #4] DEBUG -- : (1.4ms) SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC D, [2019-03-07T04:59:18.457883 #4] DEBUG -- : ActiveRecord::InternalMetadata Load (1.1ms) SELECT "ar_internal_metadata".* FROM "ar_internal_metadata" WHERE "ar_internal_metadata"."key" = $1 LIMIT $2 [["key", "environment"], ["LIMIT", 1]] D, [2019-03-07T04:59:18.466155 #4] DEBUG -- : (0.8ms) BEGIN D, [2019-03-07T04:59:18.468570 #4] DEBUG -- : SQL (1.1ms) INSERT INTO "ar_internal_metadata" ("key", "value", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "key" [["key", "environment"], ["value", "production"], ["created_at", "2019-03-07 04:59:18.466682"], ["updated_at", "2019-03-07 04:59:18.466682"]] D, [2019-03-07T04:59:18.470396 #4] DEBUG -- : (1.5ms) COMMIT D, [2019-03-07T04:59:18.471489 #4] DEBUG -- : (0.9ms) SELECT pg_advisory_unlock(4540128404952329490)通った…
まとめ
とりあえず、これで走るようになりました。
正直どれが原因でどれが解決に繋がったのかまだよく分かってないですが、個人的によく見るエラーでしたので残しておいて、詳しく分かり次第、また追記します。
詳しい方、教えていただけると助かります。
- 投稿日:2019-03-07T14:28:20+09:00
has_many :through時のdependent: :destroyの挙動
RailsのActive Recordで多対多の関連を使う時の話。ここではClubとStudentの関係を例とする。
普通に書くと、こうなると思う。class Club < ApplicationRecord has_many :club_students, dependent: :destroy has_many :students, through: :club_students end class Student < ApplicationRecord has_many :club_students, dependent: :destroy has_many :clubs, through: :club_students endただ、このようにも書ける。
class Club < ApplicationRecord has_many :club_students has_many :students, through: :club_students, dependent: :destroy end class Student < ApplicationRecord has_many :club_students has_many :clubs, through: :club_students, dependent: :destroy endこの書き方だとClubを削除した時に関連するStudentも削除されるのではないか?と思われそうだが、
throughを使った場合は中間レコードのみ削除されるので、結果的に前者と同様の挙動となる。どちらで書くかは好みの問題だろうが、個人的には後者の方が多対多の関連を1行で明示できるので、最近はこちらを使うことが多い。ただ、毎度心配になるのと、ググっても情報が出てこないため、備忘録として残しておく。
- 投稿日:2019-03-07T13:50:40+09:00
Factory_girlからFactory_botに変更したときに詰まった話
ちょっと古いシステムの改修担当になり
環境整えたときにもろもろチェックしていたらFactory_girlを使っていたので
これをFactory_botに変更するときにすこし躓いたので備忘録程度のメモ。何はともあれ、Gemの修正
Factory_girl_railsがGemfileにかかれていたので
これをFactory_bot_railsに変更してbundle install- gem "factory_girl_rails" + gem "factory_bot_rails"※うちのプロジェクトではユニコーン周りでいろいろ干渉したため
bundle install --without productionを実行正直これだけで大丈夫だと思ってた。
無事にgemのインストールが完了したのでテストしてみると
なにやらfactories以下のファイルでエラーが発生。コードも何も修正してないのになんで?って思っていろいろググる
そしたら伊藤さんの記事に出会う。
factory_bot 4.11で非推奨になった静的属性(static attributes)まさかと思って自分の
Gemfile.lockを確認しにいくと・・・factory_bot (5.0.2) activesupport (>= 4.2.0) factory_bot_rails (5.0.1) factory_bot (~> 5.0.0) railties (>= 4.2.0)Oh...
4.11どころか更に上の5.0.2まで上がってるのね。。
(2019/2/9にアプデされた様子)ということでコードを静的属性から動的属性に修正
記事内容にも書かれているように、
4.11からファクトリ定義が
静的属性のままでは警告が出る仕様に変更になっている
(そしてバージョン5で完全に削除されている)ので、
これを自分のコードにも反映。FactoryGirl.define do factory :test do trait :default do hogehoge "TEST_TEMP" fugafuga "テスト用デフォルトテンプレート" delete_flg 0 end end endから
FactoryBot.define do factory :test do trait :default do hogehoge { "TEST_TEMP" } fugafuga { "テスト用デフォルトテンプレート" } delete_flg { 0 } end end end定義に
{}をつけるだけの簡単なお仕事。
※1行目のGirlからBotへの修正も忘れずに・・!これで、テストが通るようになったのでめでたし。
今回は、修正箇所がそこまで多くなかったので
手作業で変更していったがrubocop-rspecのgemをインストールして
以下のコマンドを実行すれば一括で修正してくれるみたい(便利rubocop \ --require rubocop-rspec \ --only FactoryBot/AttributeDefinedStatically \ --auto-correct
- 投稿日:2019-03-07T13:07:25+09:00
Openbd APIを使って本レビューアプリを作成する。 ( jQuery,Ajax 使用 )
初めまして。qiita初投稿になります。
業務未経験なため、間違いがある箇所もあると思いますがご指摘頂ければと思います。
今回書くことは基礎的なことですが、私のようなrails初心者のお力になれれば幸いです。作成するレビューアプリの概要
- openbdというAPIを使用し、ajaxを利用して非同期で本の情報を取得します。
- あらかじめ用意したフォームに取得した任意の情報が自動入力され、レビューを入力し、投稿ボタンを押す事でreviewが投稿されます。
- DBには画像はURLのみ保存し、画像自体は保存しません。
- 取得する情報がない場合(画像や紹介文)は、「情報がありません」旨を表示させます。
- bootstrap4を使用しviewを作成します。
アプリ構築環境
- ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux]
- Rails 5.2.2
アプリの作成の流れ
1.アプリを作成し、必要なgem(bootstrap4等)を導入します。
2.reviewsコントローラを作成します。
3.本情報およびレビューを格納するためのReviewモデルを作成します。
4.フォームを表示するためのviewを作成します。
5.非同期(ajax)で本情報を取得するためのjsファイルを作成します。
6.投稿したレビューを表示させるためのviewを作成します。
7.railsサーバを起動します。1.アプリ作成
以下のコマンドでアプリを作成します。
rails new book_reviewアプリが作成出来たらGemfileを編集します。
cd book_review vi Gemfile以下のGemをファイルの一番下に記述します。
Gemfilegem 'haml-rails' #erbではなくhamlで記述するために導入します。 gem 'erb2haml' #既存のerbファイルをhamlに変換します。 gem 'jquery-rails' #railsでjqueryを利用するために導入します。 gem 'bootstrap' #versionをしていないのでbootstrap4がインストールされます。 gem 'bootstrap_form' #formを自動でbootstrapレイアウトにしてくれます。いつものようにbundleインストールします。
bundle installbootstrap4とbootstrap_formを使用するために以下のファイルに記述します。
book_review/app/assets/stylesheets/配下のファイルを
application.cssからapplication.scssに名前変更してください。application.scss@import "bootstrap";application.scss*= require rails_bootstrap_formsjavascriptも使用するため、以下のファイルにも以下を記述します。
//= require_tree .の上に記述してくださいapp/assets/javascripts/application.js//= require rails-ujs //= require activestorage //= require turbolinks //= require jquery3 //追加 //= require bootstrap-sprockets //追加 //= require bootstrap //追加 //= require_tree .以上で、bootstrap4とjavascriptが利用可能になります。
いよいよ、アプリ作成に入っていきます。
まずはデフォルト状態ではapplicationはerbで書かれているのでhamlに変更します。以下のコマンドを入力してください。rake haml:replace_erbs2.reviewsコントローラ作成
以下のコマンドでreviewsコントローラを作成します。
rails g controller reviews show new # showとnewを記述することで、show.html.haml,new.html.hamlも同時に作成してくれます。上記コマンドでエラーが出た場合はGemfileを編集し、sqlite3のバージョンを指定してください
Gemfilegem 'sqlite3', '~> 1.3.6'作成できたらreviews_controllerを編集します。
app/controllers/reviews_controller.rbclass ReviewsController < ApplicationController def show @review = Review.find(params[:id]) end def new @review = Review.new respond_to do |format| format.html format.json ##jsonで出力します。 end end def create @review = Review.new(review_params) if @review.save redirect_to root_path else redirect_to new_review_path end end def review_params #ストロングパラメータで制限する。 params.require(:review).permit(:name, :author, :review, :image_url, :introduction) end end合わせてレビューを投稿するためのルーティングも編集します。
config/routes.rbroot 'reviews#new' # 今回はindexページがないので、review投稿ページをrootにします。 resources :reviews #resourcesとすることで自動的にルーティングを作成してくれます。 #作成されたrouteは rails routesコマンドで確認可能です。3.Reviewモデル作成
レビューを格納するためにreviewモデルを作成します。
rails g model Review name:string author:string review:text image_url:string introduction:text上記コマンドで以下のテーブルとカラムが作成されます。
reviewsテーブル
Column Type Options name string author string review text introduction text image_url string 作成したmigrationファイルをdbにmigrateします。
rails db:migrate4.本情報取得フォーム作成
以下のviewファイルを作成し、編集します。
bootstrap_formというgemを使用しているため、form_forをbootstrap_form_forとしています。
自動でbootstrapのスタイルが適用されます。app/views/reviews/new.html.haml.container .result .panel-title 本情報取得フォーム .form-group{id:"get-book"} %input{type:"text",class:"form-control",placeholder:"ISBNを入力して下さい",id:"isbn"} .form-submit %button{type:"submit",id:"submit",class:"btn btn-outline-dark"} 本検索 .result-image = bootstrap_form_for @review ,id:"form-result" do |f| = f.text_field :name,label: "タイトル",placeholder:"本のタイトルを入力して下さい",id:"book-name" = f.text_field :author,label: "著者",placeholder:"著者の名前を入力して下さい",id:"author-name" = f.text_area :introduction,type:"hidden",hide_label: true,id:"introduction",style:"display:none" = f.text_field :image_url,type:"hidden",hide_label: true, id:"image_url" = f.text_area :review,label: "レビュー",placeholder:"レビューを入力して下さい",size: "20x10",id:"review" = f.submit "投稿",class:"btn btn-outline-dark"5.本情報取得jsファイル作成
book_review/app/assets/javascripts/の配下にreviews.js.erbを作成します。
拡張子にerbを入れているのは画像がなかった際のno_image画像をrailsのimagesフォルダから参照するためです。app/assets/javascripts/reviews.js.erb$(document).on('turbolinks:load', function() { //画像のHTMLを生成する。 function buildImage(book) { var no_image = '<div class="book_image"><img "width="200" height="200" src="<%= image_path('no_image.jpg')%>"></div>'; var image = '<div class="book_image img-thumbnail"><img "width="250" height="250" + src="' + book[0].summary.cover + '"></div>'; if (!book[0].summary.cover){ var image = no_image; //画像がなかった場合の処理 }else{ image; } return image; } //画像URLを生成する。 function imageUrl(book){ var no_image_url = '<%= image_path('/assets/no_image.jpg')%>'; var image_url = book[0].summary.cover; //".jpg"に"_0"を加える。最大サイズの画像を取得できるようになる。 var image_url = image_url.replace(".jpg", "_0.jpg"); if (!book[0].summary.cover){ var image_url = no_image_url; //画像がなかった場合の処理 }else{ image_url } return image_url; } function bookDetail (book){ var bookDetail = $.isEmptyObject(book[0].onix.CollateralDetail); if (bookDetail != true){ $('#introduction').val(book[0].onix.CollateralDetail.TextContent[0].Text); }else{ $('#introduction').val("情報がありません"); } } //著者の情報がなかった場合の処理 function authorName (book) { var bookAuthor = $.isEmptyObject(book[0].summary.author); if (bookAuthor != true){ $('#author-name').val(book[0].summary.author); }else{ $('#author-name').val("情報がありません"); } } //本の情報がなかった場合のalert function noAppendBook(){ var book = `<div class="alert alert-warning"> <strong>本情報を取得できませんでした。</strong> </div>` return book } //本の情報取得に成功した時のalert function appendBook(){ var book = `<div class="alert alert-primary"> <strong>本情報の取得に成功しました。</strong> </div>` return book } //情報取得後、再度検索バーに入力が開始されたらフォームに入力されている取得済み情報を削除する。 $('#get-book').on("keyup",function(){ $('#submit').prop('disabled', false); $('.alert').remove(); $('#book-name').val(""); $('#author-name').val(""); $('#image_url').val(""); $('#introduction').val(""); $('.book_image').empty(); }); //submitタグをクリックするとajaxで処理が開始される。 $('#submit').on("click",function(e) { e.preventDefault(); var bookName = $('#get-book').find('#isbn').prop('value'); var requestUrl = 'https://api.openbd.jp/v1/get?isbn='; requestUrl += bookName + '&pretty'; $.ajax({ type:"GET", url:requestUrl, dataType:"json" }) //通信が成功したときの処理 .done(function(data) { if (data[0] != null){ var image = buildImage(data); // resultに成功失敗のalart表示 $('.result').append(appendBook); // 本のタイトル表示 $('#book-name').val(data[0].summary.title); //hiddenタグであるimage_urlに取得した画像urlを格納 $('#image_url').val(imageUrl(data)); // 取得した本の画像を表示 $('.result-image').append(image); // 本の著者表示 authorName(data); // 本の紹介文表示 bookDetail(data); // 本情報取得に成功後 submitタグを押せないようにする。 $('#submit').prop('disabled', true); } else { // 本情報取得に失敗した際のalert表示 $('.result').append(noAppendBook); // 本情報取得に成功後 submitタグを押せないようにする。 $('#submit').prop('disabled', true); } }) // 通信に失敗した際のalert表示 .fail(function() { alert('情報の取得に失敗しました'); }); }); });本の画像が取得できなかった場合に代わりの画像を表示するため、以下のパスに以下の名前で代替画像を配置してください。
パス: app/assets/images/
ファイル名: no_image.jpgちなみに私は以下のフリー素材サイトからとりました。
http://design-ec.com/?p=55これで、ブラウザで
localhost:3000/reviews/newにアクセスすると本情報入力フォームが現れ、
「本情報取得フォーム」にISBN番号を入力する事で本の情報を取得する事ができるようになりました。もし、フォームにISBNを入力しても反応がなかった場合、coffeeファイルが呼び出されてしまっている恐れがあるので、以下のファイルを削除してください。
app/assets/javascripts/reviews.coffee6.投稿したレビューを表示
上記の作業で、review投稿ページおよび本の情報を取得するためのjsファイルを作成しましたが、
まだレビューを表示するためのviewがないので作成します。app/views/reviews/show.html.haml%section.book-images-frame.col-md-3.col-xs-12 - if @review.image_url? = image_tag "#{@review.image_url}",class: "book-images-cover",style:"height:200px;width:150px;" - else = image_tag "no_image.jpg",class: "book-images-cover",style:"height:200px;width:150px;" %section.book-content.col-md-6.col-xs-12 .book-title-frame .book-title-block = @review.name .book-attribute-frame %h2 著者 .book-author = @review.author .book-content %h2 紹介 = simple_format (@review.introduction) %h2 レビュー = simple_format (@review.review)7.railsサーバを起動
rails s #サーバ起動完成
これで本のレビューを投稿後、自動的にレビューページに遷移してくれる簡単なアプリが作成できました。
が、
まだまだ未完成なので修正していって頂ければと思います。この記事は随時修正していこうと思いますが、
記事の間違いや、もっとこうしたほうがいいよ等ございましたら、コメント頂ければ幸いです。参考にさせて頂いた記事
- 投稿日:2019-03-07T13:07:25+09:00
Openbd APIを使って簡単な本レビューアプリを作成する。 ( jQuery,Ajax 使用 )
初めまして。qiita初投稿になります。
業務未経験なため、間違いがある箇所もあると思いますがご指摘頂ければと思います。
今回書くことは基礎的なことですが、私のようなrails初心者のお力になれれば幸いです。作成するレビューアプリの概要
- openbdというAPIを使用し、ajaxを利用して非同期で本の情報を取得します。
- あらかじめ用意したフォームに取得した任意の情報が自動入力され、レビューを入力し、投稿ボタンを押す事でreviewが投稿されます。
- DBには画像はURLのみ保存し、画像自体は保存しません。
- 取得する情報がない場合(画像や紹介文)は、「情報がありません」旨を表示させます。
- bootstrap4を使用しviewを作成します。
アプリ構築環境
- ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux]
- Rails 5.2.2
アプリの作成の流れ
1.アプリを作成し、必要なgem(bootstrap4等)を導入します。
2.reviewsコントローラを作成します。
3.本情報およびレビューを格納するためのReviewモデルを作成します。
4.フォームを表示するためのviewを作成します。
5.非同期(ajax)で本情報を取得するためのjsファイルを作成します。
6.投稿したレビューを表示させるためのviewを作成します。
7.railsサーバを起動します。1.アプリ作成
以下のコマンドでアプリを作成します。
rails new book_reviewアプリが作成出来たらGemfileを編集します。
cd book_review vi Gemfile以下のGemをファイルの一番下に記述します。
Gemfilegem 'haml-rails' #erbではなくhamlで記述するために導入します。 gem 'erb2haml' #既存のerbファイルをhamlに変換します。 gem 'jquery-rails' #railsでjqueryを利用するために導入します。 gem 'bootstrap' #versionをしていないのでbootstrap4がインストールされます。 gem 'bootstrap_form' #formを自動でbootstrapレイアウトにしてくれます。いつものようにbundleインストールします。
bundle installbootstrap4とbootstrap_formを使用するために以下のファイルに記述します。
book_review/app/assets/stylesheets/配下のファイルを
application.cssからapplication.scssに名前変更してください。application.scss@import "bootstrap";application.scss*= require rails_bootstrap_formsjavascriptも使用するため、以下のファイルにも以下を記述します。
//= require_tree .の上に記述してくださいapp/assets/javascripts/application.js//= require rails-ujs //= require activestorage //= require turbolinks //= require jquery3 //追加 //= require bootstrap-sprockets //追加 //= require bootstrap //追加 //= require_tree .以上で、bootstrap4とjavascriptが利用可能になります。
いよいよ、アプリ作成に入っていきます。
まずはデフォルト状態ではapplicationはerbで書かれているのでhamlに変更します。以下のコマンドを入力してください。rake haml:replace_erbs2.reviewsコントローラ作成
以下のコマンドでreviewsコントローラを作成します。
rails g controller reviews show new # showとnewを記述することで、show.html.haml,new.html.hamlも同時に作成してくれます。上記コマンドでエラーが出た場合はGemfileを編集し、sqlite3のバージョンを指定してください
Gemfilegem 'sqlite3', '~> 1.3.6'作成できたらreviews_controllerを編集します。
app/controllers/reviews_controller.rbclass ReviewsController < ApplicationController def show @review = Review.find(params[:id]) end def new @review = Review.new respond_to do |format| format.html format.json ##jsonで出力します。 end end def create @review = Review.new(review_params) if @review.save redirect_to review_path(@review) else redirect_to new_review_path end end def review_params #ストロングパラメータで制限する。 params.require(:review).permit(:name, :author, :review, :image_url, :introduction) end end合わせてレビューを投稿するためのルーティングも編集します。
config/routes.rbroot 'reviews#new' # 今回はindexページがないので、review投稿ページをrootにします。 resources :reviews #resourcesとすることで自動的にルーティングを作成してくれます。 #作成されたrouteは rails routesコマンドで確認可能です。3.Reviewモデル作成
レビューを格納するためにreviewモデルを作成します。
rails g model Review name:string author:string review:text image_url:string introduction:text上記コマンドで以下のテーブルとカラムが作成されます。
reviewsテーブル
Column Type Options name string author string review text introduction text image_url string 作成したmigrationファイルをdbにmigrateします。
rails db:migrate4.本情報取得フォーム作成
以下のviewファイルを作成し、編集します。
bootstrap_formというgemを使用しているため、form_forをbootstrap_form_forとしています。
自動でbootstrapのスタイルが適用されます。app/views/reviews/new.html.haml.container .result .panel-title 本情報取得フォーム .form-group{id:"get-book"} %input{type:"text",class:"form-control",placeholder:"ISBNを入力して下さい",id:"isbn"} .form-submit %button{type:"submit",id:"submit",class:"btn btn-outline-dark"} 本検索 .result-image = bootstrap_form_for @review ,id:"form-result" do |f| = f.text_field :name,label: "タイトル",placeholder:"本のタイトルを入力して下さい",id:"book-name" = f.text_field :author,label: "著者",placeholder:"著者の名前を入力して下さい",id:"author-name" = f.text_area :introduction,type:"hidden",hide_label: true,id:"introduction",style:"display:none" = f.text_field :image_url,type:"hidden",hide_label: true, id:"image_url" = f.text_area :review,label: "レビュー",placeholder:"レビューを入力して下さい",size: "20x10",id:"review" = f.submit "投稿",class:"btn btn-outline-dark"5.本情報取得jsファイル作成
book_review/app/assets/javascripts/の配下にreviews.js.erbを作成します。
拡張子にerbを入れているのは画像がなかった際のno_image画像をrailsのimagesフォルダから参照するためです。app/assets/javascripts/reviews.js.erb$(document).on('turbolinks:load', function() { //画像のHTMLを生成する。 function buildImage(book) { var no_image = '<div class="book_image"><img "width="200" height="200" src="<%= image_path('no_image.jpg')%>"></div>'; var image = '<div class="book_image img-thumbnail"><img "width="250" height="250" + src="' + book[0].summary.cover + '"></div>'; if (!book[0].summary.cover){ var image = no_image; //画像がなかった場合の処理 }else{ image; } return image; } //画像URLを生成する。 function imageUrl(book){ var no_image_url = '<%= image_path('/assets/no_image.jpg')%>'; var image_url = book[0].summary.cover; //".jpg"に"_0"を加える。最大サイズの画像を取得できるようになる。 var image_url = image_url.replace(".jpg", "_0.jpg"); if (!book[0].summary.cover){ var image_url = no_image_url; //画像がなかった場合の処理 }else{ image_url } return image_url; } function bookDetail (book){ var bookDetail = $.isEmptyObject(book[0].onix.CollateralDetail); if (bookDetail != true){ $('#introduction').val(book[0].onix.CollateralDetail.TextContent[0].Text); }else{ $('#introduction').val("情報がありません"); } } //著者の情報がなかった場合の処理 function authorName (book) { var bookAuthor = $.isEmptyObject(book[0].summary.author); if (bookAuthor != true){ $('#author-name').val(book[0].summary.author); }else{ $('#author-name').val("情報がありません"); } } //本の情報がなかった場合のalert function noAppendBook(){ var book = `<div class="alert alert-warning"> <strong>本情報を取得できませんでした。</strong> </div>` return book } //本の情報取得に成功した時のalert function appendBook(){ var book = `<div class="alert alert-primary"> <strong>本情報の取得に成功しました。</strong> </div>` return book } //情報取得後、再度検索バーに入力が開始されたらフォームに入力されている取得済み情報を削除する。 $('#get-book').on("keyup",function(){ $('#submit').prop('disabled', false); $('.alert').remove(); $('#book-name').val(""); $('#author-name').val(""); $('#image_url').val(""); $('#introduction').val(""); $('.book_image').empty(); }); //submitタグをクリックするとajaxで処理が開始される。 $('#submit').on("click",function(e) { e.preventDefault(); var bookName = $('#get-book').find('#isbn').prop('value'); var requestUrl = 'https://api.openbd.jp/v1/get?isbn='; requestUrl += bookName + '&pretty'; $.ajax({ type:"GET", url:requestUrl, dataType:"json" }) //通信が成功したときの処理 .done(function(data) { if (data[0] != null){ var image = buildImage(data); // resultに成功失敗のalart表示 $('.result').append(appendBook); // 本のタイトル表示 $('#book-name').val(data[0].summary.title); //hiddenタグであるimage_urlに取得した画像urlを格納 $('#image_url').val(imageUrl(data)); // 取得した本の画像を表示 $('.result-image').append(image); // 本の著者表示 authorName(data); // 本の紹介文表示 bookDetail(data); // 本情報取得に成功後 submitタグを押せないようにする。 $('#submit').prop('disabled', true); } else { // 本情報取得に失敗した際のalert表示 $('.result').append(noAppendBook); // 本情報取得に成功後 submitタグを押せないようにする。 $('#submit').prop('disabled', true); } }) // 通信に失敗した際のalert表示 .fail(function() { alert('情報の取得に失敗しました'); }); }); });本の画像が取得できなかった場合に代わりの画像を表示するため、以下のパスに以下の名前で代替画像を配置してください。
パス: app/assets/images/
ファイル名: no_image.jpgちなみに私は以下のフリー素材サイトからとりました。
http://design-ec.com/?p=55これで、ブラウザで
localhost:3000/reviews/newにアクセスすると本情報入力フォームが現れ、
「本情報取得フォーム」にISBN番号を入力する事で本の情報を取得する事ができるようになりました。もし、フォームにISBNを入力しても反応がなかった場合、coffeeファイルが呼び出されてしまっている恐れがあるので、以下のファイルを削除してください。
app/assets/javascripts/reviews.coffee6.投稿したレビューを表示
上記の作業で、review投稿ページおよび本の情報を取得するためのjsファイルを作成しましたが、
まだレビューを表示するためのviewがないので作成します。app/views/reviews/show.html.haml%section.book-images-frame.col-md-3.col-xs-12 - if @review.image_url? = image_tag "#{@review.image_url}",class: "book-images-cover",style:"height:200px;width:150px;" - else = image_tag "no_image.jpg",class: "book-images-cover",style:"height:200px;width:150px;" %section.book-content.col-md-6.col-xs-12 .book-title-frame .book-title-block = @review.name .book-attribute-frame %h2 著者 .book-author = @review.author .book-content %h2 紹介 = simple_format (@review.introduction) %h2 レビュー = simple_format (@review.review)7.railsサーバを起動
rails s #サーバ起動完成
これで本のレビューを投稿後、自動的にレビューページに遷移してくれる簡単なアプリが作成できました。
が、
まだまだ未完成なので修正していって頂ければと思います。この記事は随時修正していこうと思いますが、
記事の間違いや、もっとこうしたほうがいいよ等ございましたら、コメント頂ければ幸いです。参考にさせて頂いた記事
- 投稿日:2019-03-07T13:07:25+09:00
【Rails】openBD APIを使って簡単な本レビューアプリを作成する。【jQuery,Ajax 】
初めまして。qiita初投稿になります。
業務未経験なため、間違いがある箇所もあると思いますがご指摘頂ければと思います。
今回書くことは基礎的なことですが、私のようなrails初心者のお力になれれば幸いです。openBD APIについて
書誌情報・書影を、だれでも自由に使える、高速なAPIで提供しているプロジェクトです。
24,747社の約76万タイトルの本の書誌情報、書影、ためし読み、書評掲載情報を利用でき、
書誌情報1件あたり1ミリ秒以下での応答と非常に高速なAPIです。公式サイト
https://openbd.jp/作成するレビューアプリの概要
- openbdというAPIを使用し、ajaxを利用して非同期で本の情報を取得します。
- あらかじめ用意したフォームに取得した任意の情報が自動入力され、レビューを入力し、投稿ボタンを押す事でreviewが投稿されます。
- DBには画像はURLのみ保存し、画像自体は保存しません。
- 取得する情報がない場合(画像や紹介文)は、「情報がありません」旨を表示させます。
- bootstrap4を使用しviewを作成します。
アプリ構築環境
- ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux]
- Rails 5.2.2
アプリの作成の流れ
1.アプリを作成し、必要なgem(bootstrap4等)を導入します。
2.reviewsコントローラを作成します。
3.本情報およびレビューを格納するためのReviewモデルを作成します。
4.フォームを表示するためのviewを作成します。
5.非同期(ajax)で本情報を取得するためのjsファイルを作成します。
6.投稿したレビューを表示させるためのviewを作成します。
7.railsサーバを起動します。1.アプリ作成
以下のコマンドでアプリを作成します。
rails new book_reviewアプリが作成出来たらGemfileを編集します。
cd book_review vi Gemfile以下のGemをファイルの一番下に記述します。
Gemfilegem 'haml-rails' #erbではなくhamlで記述するために導入します。 gem 'erb2haml' #既存のerbファイルをhamlに変換します。 gem 'jquery-rails' #railsでjqueryを利用するために導入します。 gem 'bootstrap' #versionをしていないのでbootstrap4がインストールされます。 gem 'bootstrap_form' #formを自動でbootstrapレイアウトにしてくれます。いつものようにbundleインストールします。
bundle installbootstrap4とbootstrap_formを使用するために以下のファイルに記述します。
book_review/app/assets/stylesheets/配下のファイルを
application.cssからapplication.scssに名前変更してください。application.scss@import "bootstrap";application.scss*= require rails_bootstrap_formsjavascriptも使用するため、以下のファイルにも以下を記述します。
//= require_tree .の上に記述してくださいapp/assets/javascripts/application.js//= require rails-ujs //= require activestorage //= require turbolinks //= require jquery3 //追加 //= require bootstrap-sprockets //追加 //= require bootstrap //追加 //= require_tree .以上で、bootstrap4とjavascriptが利用可能になります。
いよいよ、アプリ作成に入っていきます。
まずはデフォルト状態ではapplicationはerbで書かれているのでhamlに変更します。以下のコマンドを入力してください。rake haml:replace_erbs2.reviewsコントローラ作成
以下のコマンドでreviewsコントローラを作成します。
rails g controller reviews show new # showとnewを記述することで、show.html.haml,new.html.hamlも同時に作成してくれます。上記コマンドでエラーが出た場合はGemfileを編集し、sqlite3のバージョンを指定してください
Gemfilegem 'sqlite3', '~> 1.3.6'作成できたらreviews_controllerを編集します。
app/controllers/reviews_controller.rbclass ReviewsController < ApplicationController def show @review = Review.find(params[:id]) end def new @review = Review.new respond_to do |format| format.html format.json ##jsonで出力します。 end end def create @review = Review.new(review_params) if @review.save redirect_to review_path(@review) else redirect_to new_review_path end end def review_params #ストロングパラメータで制限する。 params.require(:review).permit(:name, :author, :review, :image_url, :introduction) end end合わせてレビューを投稿するためのルーティングも編集します。
config/routes.rbroot 'reviews#new' # 今回はindexページがないので、review投稿ページをrootにします。 resources :reviews #resourcesとすることで自動的にルーティングを作成してくれます。 #作成されたrouteは rails routesコマンドで確認可能です。3.Reviewモデル作成
レビューを格納するためにreviewモデルを作成します。
rails g model Review name:string author:string review:text image_url:string introduction:text上記コマンドで以下のテーブルとカラムが作成されます。
reviewsテーブル
Column Type Options name string author string review text introduction text image_url string 作成したmigrationファイルをdbにmigrateします。
rails db:migrate4.本情報取得フォーム作成
以下のviewファイルを作成し、編集します。
bootstrap_formというgemを使用しているため、form_forをbootstrap_form_forとしています。
自動でbootstrapのスタイルが適用されます。app/views/reviews/new.html.haml.container .result .panel-title 本情報取得フォーム .form-group{id:"get-book"} %input{type:"text",class:"form-control",placeholder:"ISBNを入力して下さい",id:"isbn"} .form-submit %button{type:"submit",id:"submit",class:"btn btn-outline-dark"} 本検索 .result-image = bootstrap_form_for @review ,id:"form-result" do |f| = f.text_field :name,label: "タイトル",placeholder:"本のタイトルを入力して下さい",id:"book-name" = f.text_field :author,label: "著者",placeholder:"著者の名前を入力して下さい",id:"author-name" = f.text_area :introduction,type:"hidden",hide_label: true,id:"introduction",style:"display:none" = f.text_field :image_url,type:"hidden",hide_label: true, id:"image_url" = f.text_area :review,label: "レビュー",placeholder:"レビューを入力して下さい",size: "20x10",id:"review" = f.submit "投稿",class:"btn btn-outline-dark"5.本情報取得jsファイル作成
book_review/app/assets/javascripts/の配下にreviews.js.erbを作成します。
拡張子にerbを入れているのは画像がなかった際のno_image画像をrailsのimagesフォルダから参照するためです。app/assets/javascripts/reviews.js.erb$(document).on('turbolinks:load', function() { //画像のHTMLを生成する。 function buildImage(book) { var no_image = '<div class="book_image"><img "width="200" height="200" src="<%= image_path('no_image.jpg')%>"></div>'; var image = '<div class="book_image img-thumbnail"><img "width="250" height="250" + src="' + book[0].summary.cover + '"></div>'; if (!book[0].summary.cover){ var image = no_image; //画像がなかった場合の処理 }else{ image; } return image; } //画像URLを生成する。 function imageUrl(book){ var no_image_url = '<%= image_path('/assets/no_image.jpg')%>'; var image_url = book[0].summary.cover; //".jpg"に"_0"を加える。最大サイズの画像を取得できるようになる。 var image_url = image_url.replace(".jpg", "_0.jpg"); if (!book[0].summary.cover){ var image_url = no_image_url; //画像がなかった場合の処理 }else{ image_url } return image_url; } function bookDetail (book){ var bookDetail = $.isEmptyObject(book[0].onix.CollateralDetail); if (bookDetail != true){ $('#introduction').val(book[0].onix.CollateralDetail.TextContent[0].Text); }else{ $('#introduction').val("情報がありません"); } } //著者の情報がなかった場合の処理 function authorName (book) { var bookAuthor = $.isEmptyObject(book[0].summary.author); if (bookAuthor != true){ $('#author-name').val(book[0].summary.author); }else{ $('#author-name').val("情報がありません"); } } //本の情報がなかった場合のalert function noAppendBook(){ var book = `<div class="alert alert-warning"> <strong>本情報を取得できませんでした。</strong> </div>` return book } //本の情報取得に成功した時のalert function appendBook(){ var book = `<div class="alert alert-primary"> <strong>本情報の取得に成功しました。</strong> </div>` return book } //情報取得後、再度検索バーに入力が開始されたらフォームに入力されている取得済み情報を削除する。 $('#get-book').on("keyup",function(){ $('#submit').prop('disabled', false); $('.alert').remove(); $('#book-name').val(""); $('#author-name').val(""); $('#image_url').val(""); $('#introduction').val(""); $('.book_image').empty(); }); //submitタグをクリックするとajaxで処理が開始される。 $('#submit').on("click",function(e) { e.preventDefault(); var bookName = $('#get-book').find('#isbn').prop('value'); var requestUrl = 'https://api.openbd.jp/v1/get?isbn='; requestUrl += bookName + '&pretty'; $.ajax({ type:"GET", url:requestUrl, dataType:"json" }) //通信が成功したときの処理 .done(function(data) { if (data[0] != null){ var image = buildImage(data); // resultに成功失敗のalart表示 $('.result').append(appendBook); // 本のタイトル表示 $('#book-name').val(data[0].summary.title); //hiddenタグであるimage_urlに取得した画像urlを格納 $('#image_url').val(imageUrl(data)); // 取得した本の画像を表示 $('.result-image').append(image); // 本の著者表示 authorName(data); // 本の紹介文表示 bookDetail(data); // 本情報取得に成功後 submitタグを押せないようにする。 $('#submit').prop('disabled', true); } else { // 本情報取得に失敗した際のalert表示 $('.result').append(noAppendBook); // 本情報取得に成功後 submitタグを押せないようにする。 $('#submit').prop('disabled', true); } }) // 通信に失敗した際のalert表示 .fail(function() { alert('情報の取得に失敗しました'); }); }); });本の画像が取得できなかった場合に代わりの画像を表示するため、以下のパスに以下の名前で代替画像を配置してください。
パス: app/assets/images/
ファイル名: no_image.jpgちなみに私は以下のフリー素材サイトからとりました。
http://design-ec.com/?p=55これで、ブラウザで
localhost:3000/reviews/newにアクセスすると本情報入力フォームが現れ、
「本情報取得フォーム」にISBN番号を入力する事で本の情報を取得する事ができるようになりました。もし、フォームにISBNを入力しても反応がなかった場合、coffeeファイルが呼び出されてしまっている恐れがあるので、以下のファイルを削除してください。
app/assets/javascripts/reviews.coffee6.投稿したレビューを表示
上記の作業で、review投稿ページおよび本の情報を取得するためのjsファイルを作成しましたが、
まだレビューを表示するためのviewがないので作成します。app/views/reviews/show.html.haml%section.book-images-frame.col-md-3.col-xs-12 - if @review.image_url? = image_tag "#{@review.image_url}",class: "book-images-cover",style:"height:200px;width:150px;" - else = image_tag "no_image.jpg",class: "book-images-cover",style:"height:200px;width:150px;" %section.book-content.col-md-6.col-xs-12 .book-title-frame .book-title-block = @review.name .book-attribute-frame %h2 著者 .book-author = @review.author .book-content %h2 紹介 = simple_format (@review.introduction) %h2 レビュー = simple_format (@review.review)7.railsサーバを起動
rails s #サーバ起動完成
これで本のレビューを投稿後、自動的にレビューページに遷移してくれる簡単なアプリが作成できました。
が、
まだまだ未完成なので修正していって頂ければと思います。この記事は随時修正していこうと思いますが、
記事の間違いや、もっとこうしたほうがいいよ等ございましたら、コメント頂ければ幸いです。参考にさせて頂いた記事
- 投稿日:2019-03-07T13:07:25+09:00
【Rails】openBD APIを使って簡単な本レビューアプリを作成する【jQuery,Ajax 】
初めまして。qiita初投稿になります。
業務未経験なため、間違いがある箇所もあると思いますがご指摘頂ければと思います。
今回書くことは基礎的なことですが、私のようなrails初心者のお力になれれば幸いです。openBD APIについて
書誌情報・書影を、だれでも自由に使える、高速なAPIで提供しているプロジェクトです。
24,747社の約76万タイトルの本の書誌情報、書影、ためし読み、書評掲載情報を利用でき、
書誌情報1件あたり1ミリ秒以下での応答と非常に高速なAPIです。公式サイト
https://openbd.jp/作成するレビューアプリの概要
- openbdというAPIを使用し、ajaxを利用して非同期で本の情報を取得します。
- あらかじめ用意したフォームに取得した任意の情報が自動入力され、レビューを入力し、投稿ボタンを押す事でreviewが投稿されます。
- DBには画像はURLのみ保存し、画像自体は保存しません。
- 取得する情報がない場合(画像や紹介文)は、「情報がありません」旨を表示させます。
- bootstrap4を使用しviewを作成します。
アプリ構築環境
- ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux]
- Rails 5.2.2
アプリの作成の流れ
1.アプリを作成し、必要なgem(bootstrap4等)を導入します。
2.reviewsコントローラを作成します。
3.本情報およびレビューを格納するためのReviewモデルを作成します。
4.フォームを表示するためのviewを作成します。
5.非同期(ajax)で本情報を取得するためのjsファイルを作成します。
6.投稿したレビューを表示させるためのviewを作成します。
7.railsサーバを起動します。1.アプリ作成
以下のコマンドでアプリを作成します。
rails new book_reviewアプリが作成出来たらGemfileを編集します。
cd book_review vi Gemfile以下のGemをファイルの一番下に記述します。
Gemfilegem 'haml-rails' #erbではなくhamlで記述するために導入します。 gem 'erb2haml' #既存のerbファイルをhamlに変換します。 gem 'jquery-rails' #railsでjqueryを利用するために導入します。 gem 'bootstrap' #versionをしていないのでbootstrap4がインストールされます。 gem 'bootstrap_form' #formを自動でbootstrapレイアウトにしてくれます。いつものようにbundleインストールします。
bundle installbootstrap4とbootstrap_formを使用するために以下のファイルに記述します。
book_review/app/assets/stylesheets/配下のファイルを
application.cssからapplication.scssに名前変更してください。application.scss@import "bootstrap";application.scss*= require rails_bootstrap_formsjavascriptも使用するため、以下のファイルにも以下を記述します。
//= require_tree .の上に記述してくださいapp/assets/javascripts/application.js//= require rails-ujs //= require activestorage //= require turbolinks //= require jquery3 //追加 //= require bootstrap-sprockets //追加 //= require bootstrap //追加 //= require_tree .以上で、bootstrap4とjavascriptが利用可能になります。
いよいよ、アプリ作成に入っていきます。
まずはデフォルト状態ではapplicationはerbで書かれているのでhamlに変更します。以下のコマンドを入力してください。rake haml:replace_erbs2.reviewsコントローラ作成
以下のコマンドでreviewsコントローラを作成します。
rails g controller reviews show new # showとnewを記述することで、show.html.haml,new.html.hamlも同時に作成してくれます。上記コマンドでエラーが出た場合はGemfileを編集し、sqlite3のバージョンを指定してください
Gemfilegem 'sqlite3', '~> 1.3.6'作成できたらreviews_controllerを編集します。
app/controllers/reviews_controller.rbclass ReviewsController < ApplicationController def show @review = Review.find(params[:id]) end def new @review = Review.new respond_to do |format| format.html format.json ##jsonで出力します。 end end def create @review = Review.new(review_params) if @review.save redirect_to review_path(@review) else redirect_to new_review_path end end def review_params #ストロングパラメータで制限する。 params.require(:review).permit(:name, :author, :review, :image_url, :introduction) end end合わせてレビューを投稿するためのルーティングも編集します。
config/routes.rbroot 'reviews#new' # 今回はindexページがないので、review投稿ページをrootにします。 resources :reviews #resourcesとすることで自動的にルーティングを作成してくれます。 #作成されたrouteは rails routesコマンドで確認可能です。3.Reviewモデル作成
レビューを格納するためにreviewモデルを作成します。
rails g model Review name:string author:string review:text image_url:string introduction:text上記コマンドで以下のテーブルとカラムが作成されます。
reviewsテーブル
Column Type Options name string author string review text introduction text image_url string 作成したmigrationファイルをdbにmigrateします。
rails db:migrate4.本情報取得フォーム作成
以下のviewファイルを作成し、編集します。
bootstrap_formというgemを使用しているため、form_forをbootstrap_form_forとしています。
自動でbootstrapのスタイルが適用されます。app/views/reviews/new.html.haml.container .result .panel-title 本情報取得フォーム .form-group{id:"get-book"} %input{type:"text",class:"form-control",placeholder:"ISBNを入力して下さい",id:"isbn"} .form-submit %button{type:"submit",id:"submit",class:"btn btn-outline-dark"} 本検索 .result-image = bootstrap_form_for @review ,id:"form-result" do |f| = f.text_field :name,label: "タイトル",placeholder:"本のタイトルを入力して下さい",id:"book-name" = f.text_field :author,label: "著者",placeholder:"著者の名前を入力して下さい",id:"author-name" = f.text_area :introduction,type:"hidden",hide_label: true,id:"introduction",style:"display:none" = f.text_field :image_url,type:"hidden",hide_label: true, id:"image_url" = f.text_area :review,label: "レビュー",placeholder:"レビューを入力して下さい",size: "20x10",id:"review" = f.submit "投稿",class:"btn btn-outline-dark"5.本情報取得jsファイル作成
book_review/app/assets/javascripts/の配下にreviews.js.erbを作成します。
拡張子にerbを入れているのは画像がなかった際のno_image画像をrailsのimagesフォルダから参照するためです。app/assets/javascripts/reviews.js.erb$(document).on('turbolinks:load', function() { //画像のHTMLを生成する。 function buildImage(book) { var no_image = '<div class="book_image"><img "width="200" height="200" src="<%= image_path('no_image.jpg')%>"></div>'; var image = '<div class="book_image img-thumbnail"><img "width="250" height="250" + src="' + book[0].summary.cover + '"></div>'; if (!book[0].summary.cover){ var image = no_image; //画像がなかった場合の処理 }else{ image; } return image; } //画像URLを生成する。 function imageUrl(book){ var no_image_url = '<%= image_path('/assets/no_image.jpg')%>'; var image_url = book[0].summary.cover; //".jpg"に"_0"を加える。最大サイズの画像を取得できるようになる。 var image_url = image_url.replace(".jpg", "_0.jpg"); if (!book[0].summary.cover){ var image_url = no_image_url; //画像がなかった場合の処理 }else{ image_url } return image_url; } function bookDetail (book){ var bookDetail = $.isEmptyObject(book[0].onix.CollateralDetail); if (bookDetail != true){ $('#introduction').val(book[0].onix.CollateralDetail.TextContent[0].Text); }else{ $('#introduction').val("情報がありません"); } } //著者の情報がなかった場合の処理 function authorName (book) { var bookAuthor = $.isEmptyObject(book[0].summary.author); if (bookAuthor != true){ $('#author-name').val(book[0].summary.author); }else{ $('#author-name').val("情報がありません"); } } //本の情報がなかった場合のalert function noAppendBook(){ var book = `<div class="alert alert-warning"> <strong>本情報を取得できませんでした。</strong> </div>` return book } //本の情報取得に成功した時のalert function appendBook(){ var book = `<div class="alert alert-primary"> <strong>本情報の取得に成功しました。</strong> </div>` return book } //情報取得後、再度検索バーに入力が開始されたらフォームに入力されている取得済み情報を削除する。 $('#get-book').on("keyup",function(){ $('#submit').prop('disabled', false); $('.alert').remove(); $('#book-name').val(""); $('#author-name').val(""); $('#image_url').val(""); $('#introduction').val(""); $('.book_image').empty(); }); //submitタグをクリックするとajaxで処理が開始される。 $('#submit').on("click",function(e) { e.preventDefault(); var bookName = $('#get-book').find('#isbn').prop('value'); var requestUrl = 'https://api.openbd.jp/v1/get?isbn='; requestUrl += bookName + '&pretty'; $.ajax({ type:"GET", url:requestUrl, dataType:"json" }) //通信が成功したときの処理 .done(function(data) { if (data[0] != null){ var image = buildImage(data); // resultに成功失敗のalart表示 $('.result').append(appendBook); // 本のタイトル表示 $('#book-name').val(data[0].summary.title); //hiddenタグであるimage_urlに取得した画像urlを格納 $('#image_url').val(imageUrl(data)); // 取得した本の画像を表示 $('.result-image').append(image); // 本の著者表示 authorName(data); // 本の紹介文表示 bookDetail(data); // 本情報取得に成功後 submitタグを押せないようにする。 $('#submit').prop('disabled', true); } else { // 本情報取得に失敗した際のalert表示 $('.result').append(noAppendBook); // 本情報取得に成功後 submitタグを押せないようにする。 $('#submit').prop('disabled', true); } }) // 通信に失敗した際のalert表示 .fail(function() { alert('情報の取得に失敗しました'); }); }); });本の画像が取得できなかった場合に代わりの画像を表示するため、以下のパスに以下の名前で代替画像を配置してください。
パス: app/assets/images/
ファイル名: no_image.jpgちなみに私は以下のフリー素材サイトからとりました。
http://design-ec.com/?p=55これで、ブラウザで
localhost:3000/reviews/newにアクセスすると本情報入力フォームが現れ、
「本情報取得フォーム」にISBN番号を入力する事で本の情報を取得する事ができるようになりました。もし、フォームにISBNを入力しても反応がなかった場合、coffeeファイルが呼び出されてしまっている恐れがあるので、以下のファイルを削除してください。
app/assets/javascripts/reviews.coffee6.投稿したレビューを表示
上記の作業で、review投稿ページおよび本の情報を取得するためのjsファイルを作成しましたが、
まだレビューを表示するためのviewがないので作成します。app/views/reviews/show.html.haml%section.book-images-frame.col-md-3.col-xs-12 - if @review.image_url? = image_tag "#{@review.image_url}",class: "book-images-cover",style:"height:200px;width:150px;" - else = image_tag "no_image.jpg",class: "book-images-cover",style:"height:200px;width:150px;" %section.book-content.col-md-6.col-xs-12 .book-title-frame .book-title-block = @review.name .book-attribute-frame %h2 著者 .book-author = @review.author .book-content %h2 紹介 = simple_format (@review.introduction) %h2 レビュー = simple_format (@review.review)7.railsサーバを起動
rails s #サーバ起動完成
これで本のレビューを投稿後、自動的にレビューページに遷移してくれる簡単なアプリが作成できました。
が、
まだまだ未完成なので修正していって頂ければと思います。この記事は随時修正していこうと思いますが、
記事の間違いや、もっとこうしたほうがいいよ等ございましたら、コメント頂ければ幸いです。参考にさせて頂いた記事
- 投稿日:2019-03-07T13:01:12+09:00
[学習用]Rails5で画像投稿 CarrierWaveで最速保存
うっかり忘れたので構築した手順を忘れない様にメモ。
scaffold で一括作成
$ rails g scaffold shop title:string content:text name:string cat_id:integer user_id:integer image:stringまず、scaffold で一括作成。
ハマったポイント
このときimage:string も一緒に作ってしまう。
ここを忘れてて、画像が登録されないerrorに悩まされる。もし追加し忘れたら
$ rails g migration add_image_column_to_shops image:string $ rails db:migrateこれで大丈夫。
Gem CarrierWaveの追加
gem 'carrierwave'Gemfile に上記を追加して
$ bundleアップローダークラス生成
$ rails g uploader imageapp/uploader/image_uploader.rb が作成される
CarrierWave編集
app/uploaders/image_uploader.rbclass ImageUploader < CarrierWave::Uploader::Base storage :file # storage :fog def store_dir "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" end def extension_whitelist %w(jpg jpeg gif png) end # 画像名をリネームさせる(日付時間はダメ絶対) def filename "#{secure_token}.#{file.extension}" if original_filename.present? end protected def secure_token var = :"@#{mounted_as}_secure_token" model.instance_variable_get(var) or model.instance_variable_set(var, SecureRandom.uuid) end endはまったポイント
"#{Time.zone.now.strftime('%Y%m%d%H%M%S')}.jpg" if original_filename.present?
タイムゾーンにするとリサイズ時にエラーが出てサイズの変更ができなくなる。
エラー名が全然違うので、全くわからなかった。
RMagick入ってないよとかMiniMagick入ってないよとかそんなerrorが出てテンパる。追加
/app/models/shop.rbclass Shop < ApplicationRecord mount_uploader :image, ImageUploader endパラメータの確認
/app/controllers/posts_controller.rbprivate # Use callbacks to share common setup or constraints between actions. def set_shop @shop = Shop.find(params[:id]) end # Never trust parameters from the scary internet, only allow the white list through. def shop_params params.require(:shop).permit(:title, :content, :cat_id, :name, :user_id, :image) endimage をscaffoldより後から追加したなら :imageを追加する。
image をscaffoldで追加したなら入っているか確認する。画像が表示できる様にする
画像を登録
/app/views/_form.html.erb<%= form.label :image %> <%= form.file_field :image %>変更、新規、編集の時に追加できるように。
表示側の追加
/app/views/show.html.erb<% if @shop.image? %> <%= image_tag @shop.image.url %> <% end %>
- 投稿日:2019-03-07T13:01:12+09:00
[学習用]Rails5:CarrierWaveで画像投稿+rmagickでサムネイル保存+画像名ランダム化
うっかり忘れたので構築した手順を忘れない様にメモ。
※ローカルテスト用。Herokuには保存できないので、AWSのS3に保存するときは
保存先を違うものに変更する必要がある。scaffold で一括作成
$ rails g scaffold shop title:string content:text name:string cat_id:integer user_id:integer image:stringまず、scaffold で一括作成。
ハマったポイント
このときimage:string も一緒に作ってしまう。
ここを忘れてて、画像が登録されないerrorに悩まされる。もし追加し忘れたら
$ rails g migration add_image_column_to_shops image:string $ rails db:migrateこれで大丈夫。
Gem CarrierWaveの追加
gem 'carrierwave'Gemfile に上記を追加して
$ bundleアップローダークラス生成
$ rails g uploader imageapp/uploader/image_uploader.rb が作成される
CarrierWave編集
app/uploaders/image_uploader.rbclass ImageUploader < CarrierWave::Uploader::Base storage :file # storage :fog def store_dir "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" end def extension_whitelist %w(jpg jpeg gif png) end # 画像名をリネームさせる(日付時間はダメ絶対) def filename "#{secure_token}.#{file.extension}" if original_filename.present? end protected def secure_token var = :"@#{mounted_as}_secure_token" model.instance_variable_get(var) or model.instance_variable_set(var, SecureRandom.uuid) end endはまったポイント
"#{Time.zone.now.strftime('%Y%m%d%H%M%S')}.jpg" if original_filename.present?
タイムゾーンにするとリサイズ時にエラーが出てサイズの変更ができなくなる。
エラー名が全然違うので、全くわからなかった。
RMagick入ってないよとかMiniMagick入ってないよとかそんなerrorが出てテンパる。追加
/app/models/shop.rbclass Shop < ApplicationRecord mount_uploader :image, ImageUploader endパラメータの確認
/app/controllers/posts_controller.rbprivate # Use callbacks to share common setup or constraints between actions. def set_shop @shop = Shop.find(params[:id]) end # Never trust parameters from the scary internet, only allow the white list through. def shop_params params.require(:shop).permit(:title, :content, :cat_id, :name, :user_id, :image) endimage をscaffoldより後から追加したなら :imageを追加する。
image をscaffoldで追加したなら入っているか確認する。画像が表示できる様にする
画像を登録
/app/views/_form.html.erb<%= form.label :image %> <%= form.file_field :image %>変更、新規、編集の時に追加できるように。
表示側の追加
/app/views/show.html.erb<% if @shop.image? %> <%= image_tag @shop.image.url %> <% end %>画像のリサイズ
gem 'rmagick'$ bundleCarrierWave編集
app/uploaders/image_uploader.rbclass ImageUploader < CarrierWave::Uploader::Base # Include RMagick or MiniMagick support: include CarrierWave::RMagick # include CarrierWave::MiniMagick # Choose what kind of storage to use for this uploader: storage :file # storage :fog # Override the directory where uploaded files will be stored. # This is a sensible default for uploaders that are meant to be mounted: def store_dir "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" end # ファイルサイズに制限をつける def size_range 1..5.megabytes end # 画像の上限を640x480にする process :resize_to_limit => [640, 640] # サムネイル保存する version :thumb do process :resize_to_limit => [320, 320] end # 保存形式 process :convert => 'jpg' def extension_whitelist %w(jpg jpeg gif png) end # 拡張子が同じでないとGIFをJPGとかにコンバートできない def filename super.chomp(File.extname(super)) + '.jpg' if original_filename.present? end # ファイル名を日付にすると不具合が出る def filename "#{secure_token}.#{file.extension}" if original_filename.present? end protected def secure_token var = :"@#{mounted_as}_secure_token" model.instance_variable_get(var) or model.instance_variable_set(var, SecureRandom.uuid) end endViewにサムネイル追加
/app/views/show.html.erb<% if @shop.image? %> <%= image_tag @shop.image.url %> <% end %> <%= image_tag @shop.image.url(:thumb) %>これで640画像と320のサムネイル画像が表示される
これで忘れても大丈夫なはず。参考にしたサイト
https://nyoken.com/rails-carrierwave
- 投稿日:2019-03-07T07:31:28+09:00
【Rails】1つの検索フォームで複数カラムをまたいで検索する方法
検索フォームの実装は簡単
検索フォームは意外と簡単に実装出来ます。下記の記事など参考にすればすぐ出来ます。
・railsで検索フォームを作ろう!!
・Ruby on Rails 検索機能拡張 (railsチュートリアル)
・【開発メモ】Railsアプリに検索機能を実装する方法をわかりやすくまとめてみた。ここからが本題
上記の記事はいずれも1つのカラムに対して検索をかける方法です。
複数のカラムを1つの検索フォームだけで検索したい場合は下記のようにすれば出来ます。これも知っていれば簡単です。適切なオブジェクト名.where(['検索したいカラム名 ? OR 検索したいカラム名 LIKE ? OR 検索したいカラム名 LIKE ?', "%#{search}%", "%#{search}%", "%#{search}%"])検索したいカラムが3つある場合は、"%#{search}%"も3つつけましょう。そうすれば1つのフォームで複数カラムまたいで検索出来ます!
- 投稿日:2019-03-07T01:49:45+09:00
[備忘録]プログラミング学習_2(webエンジニアの将来、言語概念の学習)
投稿目的
個人的な学習記録
同じ初心者の技術力・モチベーションの向上本日の学習内容(webエンジニアの将来、言語概念の学習)
昨日(_1)、jsやReactの文法などの学習を行ったが、技術の需要や将来性、用途について一度考えようと思い今日は調べごとを中心に行った。
調べた事
1.Reactはjsのライブラリ。フレームワークじゃない。
ライブラリは各用途の便利グッズまとめ、フレームワークは起承転結楽々テンプレートって理解になった。
参考URL:(https://qita.com/azuki8/items/ad7710fdefaedc63e3f7)
2.KENTAさん動画にてキャリア考察
年齢・勉強・好奇心のリスクについて考えさせられた。業界の成熟的に50歳以上の正社員さんの数が現状少ないが、今の30代が20年後どのようなキャリアになっているのか気になる。何も考えずに楽しそうだけでWeb系エンジニアになるのは危険かもしれない。(Web系エンジニアという職業の3つのリスクである「年齢」「勉強」「好奇心」)
参考URL: (https://www.youtube.com/watch?v=YuOYjxpMI4w)
3.KENTAさん動画にて「わらしべ長者戦略」
私自身、新卒+テックエキスパートの手札で現在の内定先を獲得したので、業務を通して自分自身の手札を増やしつつステップアップする方法は正しいと感じた。一つの言語に固執して、廃れる可能性を日々考えるのは精神的にもよくないしね。
参考URL: (https://www.youtube.com/watch?v=eElCAwuDwsk)