- 投稿日:2019-04-15T23:48:20+09:00
model内のインスタンスメソッドの中でインスタンスの属性値を取得する
経緯
- 自分が書いた過去のコード(Ruby書き始めだった頃のもの)を見ていると、「今はとりあえずこのようにしか書けないけど、本当はもっとよりよく書けるはずだ」と思っていた部分が目に入ったので、直します。
- 表題の件について、誰か同じように詰まった方の参考になれればいいのですが。。。
修正前
- 以下のようなコードです。しかしすごい書き方していますね。。。
game.rbdef get_gameset_msg gameset_msg = "試合中" if self[:gameset_flag] gameset_msg = "試合終了" end return gameset_msg end修正後
- カラム名は修正していませんが、「gameset_flag」は「is_gameset」とかの方がいいんでしょうか。。。
game.rbdef get_gameset_msg self.gameset_flag ? "試合終了" : "試合中" endポイント
- 基本的な取得方法(修正後と同じコード)
- model内のインスタンスメソッドの中では、selfでインスタンス本体を指します。
self.xxx
で属性値を取得できます。(こういう書き方って、あんまり載ってない気がするのですが。。。)game.rbdef get_gameset_msg self.gameset_flag ? "試合終了" : "試合中" end
- 属性名を動的に生成する場合
- イニングごとの得点を合計した値が欲しい場合などは、動的にカラム名を生成することでコード量を減らせますが、この場合はハッシュのvalueを取得するように書きます。
self.xxx
のようには書けません。game.rbdef get_sum_top sum_top = 0 9.times {|n| str_top = "top" << (n + 1).to_s sum_top += self[str_top].to_i } sum_top end
- 属性名を動的に生成する場合(その2)
- 上記のコードは、以下のように
send
メソッドを使って書くこともできます。メソッド名を文字列で指定して実行する場合に使えるメソッドです。ただ、今回のような場合は上記のようにself[str_top]
の方が短くていいですかね。game.rbdef get_sum_top sum_top = 0 15.times {|n| str_top = "top" << (n + 1).to_s sum_top += self.send(str_top).to_i } sum_top end参考
- 投稿日:2019-04-15T23:23:06+09:00
rails devise name login
はじめに
deviseでログイン機能を作成するときに名前とパスワードでログイン機能を作成したい方向けに記事を書きます。
基本的にコピペのみで完成します。
コードを理解してください。環境
- macOS mojave
- rbenv 1.1.1
- ruby 2.5.3p105
- Rails 5.2.3
実装
email, passwordで新規登録、ログインする機能の作成
$ rails new devise_name $ cd devise_name $ rails g controller home top after_loginconfig/routes.rbRails.application.routes.draw do root 'home#top' get 'home/after_login' endGemfile...追記 gem 'devise'$ bundle $ rails g devise:install $ rails g devise User $ rails db:migrateapp/views/home/top.html.erb<%= link_to '新規登録', new_user_registration_path %> <%= link_to 'ログイン', new_user_session_path %>app/controllers/application_controller.rbclass ApplicationController < ActionController::Base def after_sign_in_path_for(resource) home_after_login_path end endapp/views/home/after_login.html.erb<%= link_to "ログアウト", destroy_user_session_path, method: :delete %>name, email, passwordで新規登録、name, passwordでログインする機能の作成
- nameカラムの作成 & emailのバリデーション系を全て外す
$ rails g migration AddNameToUsers name:string $ rails g migration ChangeColumnToUsers $ rails g migration remove_index_email_from_usersdb/migrate/日時_change_column_to_users.rbclass ChangeColumnToUsers < ActiveRecord::Migration[5.2] # 変更内容 def up change_column :users, :email, :string, null: true, default: "" end # 変更前の状態 def down change_column :users, :email, :string, null: false, default: "" end enddb/migrate/日時_remove_index_email_from_users.rbclass RemoveIndexEmailFromUsers < ActiveRecord::Migration[5.2] def change remove_index :users, column: :email, unique: true end end$ rails db:migrateconfig/initializers/devise.rb...編集 config.authentication_keys = [:name]app/models/user.rb...追記 def email_required? false end def email_changed? false end
- 新規登録フォーム, ログインフォームの編集
$ rails g devise:viewsapp/views/devise/registrations/new.html.erb...追記 <div class="field"> <%= f.label :name %><br /> <%= f.text_field :name, autofocus: true, autocomplete: "name" %> </div>app/views/devise/sessions/new.html.erb...編集 <div class="field"> <%= f.label :name %><br /> <%= f.text_field :name, autofocus: true, autocomplete: "name" %> </div>
- パラメータの許可
app/controllers/application_controller.rbclass ApplicationController < ActionController::Base before_action :configure_permitted_parameters, if: :devise_controller? def after_sign_in_path_for(resource) home_after_login_path end protected def configure_permitted_parameters devise_parameter_sanitizer.permit(:sign_up, keys: [:name, :email]) devise_parameter_sanitizer.permit(:sign_in, keys: [:name]) end end以上。
完成コード
- 投稿日:2019-04-15T23:23:06+09:00
[Ruby on Rails] devise name(名前)でログイン
はじめに
deviseでログイン機能を作成するときに名前とパスワードでログイン機能を作成したい方向けに記事を書きます。
基本的にコピペのみで完成します。
コードを理解してください。環境
- macOS mojave
- rbenv 1.1.1
- ruby 2.5.3
- Rails 5.2.3
実装
email, passwordで新規登録、ログインする機能の作成
$ rails new devise_name $ cd devise_name $ rails g controller home top after_loginconfig/routes.rbRails.application.routes.draw do root 'home#top' get 'home/after_login' endGemfile...追記 gem 'devise'$ bundle $ rails g devise:install $ rails g devise User $ rails db:migrateapp/views/home/top.html.erb<%= link_to '新規登録', new_user_registration_path %> <%= link_to 'ログイン', new_user_session_path %>app/controllers/application_controller.rbclass ApplicationController < ActionController::Base def after_sign_in_path_for(resource) home_after_login_path end endapp/views/home/after_login.html.erb<%= link_to "ログアウト", destroy_user_session_path, method: :delete %>name, email, passwordで新規登録、name, passwordでログインする機能の作成
- nameカラムの作成 & emailのバリデーション系を全て外す
$ rails g migration AddNameToUsers name:string $ rails g migration ChangeColumnToUsers $ rails g migration remove_index_email_from_usersdb/migrate/日時_change_column_to_users.rbclass ChangeColumnToUsers < ActiveRecord::Migration[5.2] # 変更内容 def up change_column :users, :email, :string, null: true, default: "" end # 変更前の状態 def down change_column :users, :email, :string, null: false, default: "" end enddb/migrate/日時_remove_index_email_from_users.rbclass RemoveIndexEmailFromUsers < ActiveRecord::Migration[5.2] def change remove_index :users, column: :email, unique: true end end$ rails db:migrateconfig/initializers/devise.rb...編集 config.authentication_keys = [:name]app/models/user.rb...追記 def email_required? false end def email_changed? false end
- 新規登録フォーム, ログインフォームの編集
$ rails g devise:viewsapp/views/devise/registrations/new.html.erb...追記 <div class="field"> <%= f.label :name %><br /> <%= f.text_field :name, autofocus: true, autocomplete: "name" %> </div>app/views/devise/sessions/new.html.erb...編集 <div class="field"> <%= f.label :name %><br /> <%= f.text_field :name, autofocus: true, autocomplete: "name" %> </div>
- パラメータの許可
app/controllers/application_controller.rbclass ApplicationController < ActionController::Base before_action :configure_permitted_parameters, if: :devise_controller? def after_sign_in_path_for(resource) home_after_login_path end protected def configure_permitted_parameters devise_parameter_sanitizer.permit(:sign_up, keys: [:name, :email]) devise_parameter_sanitizer.permit(:sign_in, keys: [:name]) end end以上。
完成コード
- 投稿日:2019-04-15T22:42:00+09:00
rails aborted! StandardError: An error has occurred, this and all later migrations canceled:
初心者がrails tutorialでscaffoldでUserモデルを生成後、rails db:migrateを入力したときに遭遇したエラー処理について共有します。
mac-no-MacBookPro:toy_app mac$ ./qs rails db:migrate Starting toy_app_db_1 ... done == 20190413154520 CreateUsers: migrating ====================================== -- create_table(:users) rails aborted! StandardError: An error has occurred, this and all later migrations canceled: PG::DuplicateTable: ERROR: relation "users" already exists : CREATE TABLE "users" ("id" bigserial primary key, "name" character varying, "email" character varying, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL)migrateした後にusers tableが既に存在すると表示されました。
そこで$ rails db:migrate:reset $ rails db:migrateresetのコード入力後、再度migrateを試みるも状況は変わらず。
最終的には下記のようにエディタから直接いじり、解決できました。DBのmigrateファイルの中の今回DBに反映させたかった部分を一度コメントアウト。
class CreateMicroposts < ActiveRecord::Migration[5.2] def change #create_table :microposts do |t| #t.text :content #t.integer :user_id #t.timestamps #end end endその後
$ rails db:migrateそして、この後はコメントアウトした「#」の文字を消します。
class CreateMicroposts < ActiveRecord::Migration[5.2] def change create_table :microposts do |t| t.text :content t.integer :user_id t.timestamps end end endそして最後に以下のコードを打ち込み、解決しました。
$ rails db:migrate:down VERSION= <該当のmigrateファイル名> $ rails db:migrate
- 投稿日:2019-04-15T20:28:01+09:00
Rails6 のちょい足しな新機能を試す3(rails server -u編)
はじめに
Rails 6 に追加されそうな新機能を試す第3段。
rails server
の-u
オプション機能です。
記載時点では、Rails は 6.0.0.beta3 です。gem install rails --prerelease
でインストールできます。$ rails --version Rails 6.0.0.beta3u``単純なCRUD機能をscaffold で作る
新機能を試すために、scaffold で単純なCRUD機能を作ってみます。
$ rails new sandbox_6_0_0b3 $ cd sandbox_6_0_0b3 $ rails g scaffold User name従来の機能
rails server のオプションを調べてみます。
$ rails s --help Usage: rails server [puma, thin etc] [options] Options: -p, [--port=port] # Runs Rails on the specified port - defaults to 3000. -b, [--binding=IP] # Binds Rails to the specified IP - defaults to 'localhost' in development and '0.0.0.0' in other environments'. -c, [--config=file] # Uses a custom rackup configuration. # Default: config.ru -d, [--daemon], [--no-daemon] # Runs server as a Daemon. -e, [--environment=name] # Specifies the environment to run this server under (development/test/production). -P, [--pid=PID] # Specifies the PID file. # Default: tmp/pids/server.pid -C, [--dev-caching], [--no-dev-caching] # Specifies whether to perform caching in development. [--early-hints], [--no-early-hints] # Enables HTTP/2 early hints.
-u
オプションはありません。新機能
Rails 6.0.0beta3 で試してみます。
$ rails s --help Usage: rails server [thin/puma/webrick] [options] Options: -p, [--port=port] # Runs Rails on the specified port - defaults to 3000. -b, [--binding=IP] # Binds Rails to the specified IP - defaults to 'localhost' in development and '0.0.0.0' in other environments'. -c, [--config=file] # Uses a custom rackup configuration. # Default: config.ru -d, [--daemon], [--no-daemon] # Runs server as a Daemon. -e, [--environment=name] # Specifies the environment to run this server under (development/test/production). -u, [--using=name] # Specifies the Rack server used to run the application (thin/puma/webrick). -P, [--pid=PID] # Specifies the PID file. # Default: tmp/pids/server.pid -C, [--dev-caching], [--no-dev-caching] # Specifies whether to perform caching in development. [--early-hints], [--no-early-hints] # Enables HTTP/2 early hints. [--log-to-stdout], [--no-log-to-stdout] # Whether to log to stdout. Enabled by default in development when not daemonized.
-u
オプションで rack サーバーを指定するようになってます。では、試してみましょう。
$ rails s -u puma => Booting Puma => Rails 6.0.0.beta3 application starting in development => Run `rails server --help` for more startup options Puma starting in single mode... * Version 3.12.1 (ruby 2.6.2-p47), codename: Llamas in Pajamas * Min threads: 5, max threads: 5 * Environment: development * Listening on tcp://localhost:3000 Use Ctrl-C to stopwebrickも試してみます。
$ rails s -u webrick => Booting WEBrick => Rails 6.0.0.beta3 application starting in development http://localhost:3000 => Run `rails server --help` for more startup options [2019-04-15 10:47:39] INFO WEBrick 1.4.2 [2019-04-15 10:47:39] INFO ruby 2.6.2 (2019-03-13) [x86_64-linux-musl] [2019-04-15 10:47:39] INFO WEBrick::HTTPServer#start: pid=977 port=3000せっかくなので、
thin
とfalcon
も試してみます。 Gemfile にthin
とfalcon
を追加します。Gemfilegem 'thin' gem 'falcon'
bundle install
を実行した後、thin
を試してみます。$ rails s -u thin => Booting Thin => Rails 6.0.0.beta3 application starting in development http://localhost:3000 => Run `rails server --help` for more startup options Thin web server (v1.7.2 codename Bachmanity) Maximum connections set to 1024 Listening on localhost:3000, CTRL+C to stop最後は
falcon
です。$ rails s -u falcon -b 0.0.0.0 => Booting Falcon => Rails 6.0.0.beta3 application starting in development http://0.0.0.0:3000 => Run `rails server --help` for more startup options
falcon
は-b
オプションを指定しないとエラーになりました。 falcon もそのまま使えるとわかったのは収穫でした。参考情報
- 投稿日:2019-04-15T20:05:58+09:00
【Rails】オラ自作のブックマークシェアWebアプリで『作業が捗るおやつ・ドリンク集』を紹介すっぞ!
オッス(Z戦士)
突然ですが、作業中の"おやつ"と"飲み物"って生きてく上での酸素と同じくらい大切だと思うんですよね。
ぼくは大量のコードと長時間向き合ってもビクともしない超(スーパー)エンジニア人ではないので、
作業中は仙豆に相当する"おやつ"と"飲み物"で都度回復しないと、「hassoubeat(ぼく)は置いてきた...ハッキリ言ってこれからの業務にはついていけない...」
といった具合に、天さん(上司)に見捨てられること請け合いです。
そんなぼくをギリギリ戦いに参加できるヤムチャレベルまで引き上げてくれるドーピングアイテム。それが、作業中の"おやつ"と"飲み物"なのです。
今回はそんなぼくが愛好する"おやつ"、"飲み物"を...
オラが作ったRailsのWebアプリで『作業が捗るおやつ・ドリンク集』をいっちょ紹介してみっか!!!(唐突)
作業が捗るおやつ・ドリンク集 by hassoubeat LinkS
赤枠の箇所をクリック・タッチしてもらえればブックマークに対して一言コメントが読めるゾ個人的に"きかんしゃトーマスとなかまたちチューイングキャンディ」と「マテ茶」は実力はあるのに、あまり知られていないのが残念で仕方ないです。
もし興味を持っていただけたら、リンク先からポチってお試しいただけると嬉しいです。
...。
Webアプリ側にコメントを書いているので当たり前なのですが、おやつに関して書くことがなくなってしまいました。このまま終わるのも寂しいという皆様のためにぃ(ねっとり)
ここから先は今回開発したWebアプリの話でもしようかと思います。
(おやつの話以外)興味ないね(魔晄中毒者)という方は、
オススメの"おやつ"と"飲み物"をコメントに書いてからブラウザバックしてもらえたら嬉しいゾ自作Webアプリの紹介
今回開発したWebアプリ『LinkS(リンクス)』の紹介にイクゾー!
そもそもこのアプリはなんなの?
コメントを付けたブックマーク集をワンクリックで公開してSNSにも簡単に共有できるブックマークシェアWebアプリです。
実際にシェアするまでの流れを見てもらいましょう。
1.フォルダー作成
ブックマークの公開・共有はフォルダー単位で行われるため、まずフォルダーを。
公開に設定しない限り、自分だけのブックマーク集としても利用できます。2.ブックマーク登録
さっき作ったフォルダーにブックマークを登録します。Just Monika.3.フォルダー公開
フォルダーの公開設定を公開に変更することで、ログインしている本人以外にもURLを叩けばそのフォルダーが見れるように。4.シェア
おすすめゲームのPV集 by hassoubeat LinkS
URLを直接シェアする以外にも、LinkSからSNSに直接シェアすることもできます。ちなみにスマホでもちゃんと使えます
...。
機能がシンプル過ぎるので、話すことがなくなりました。
一応申し訳程度にいいね機能、管理機能とかも実装してます。現在β版ですが、もし気になる人がいたら捨てアドでアカウント登録して使ってみてくれたら嬉しいゾ。
なんで作ろうと思い立ったワケ?
理由は2つありますねぇ!
1.RubyOnRailsのポートフォリオを作りたかった
2.弟がHTMLの勉強を始めるにあたって何をしたらいいか聞いてきた1.RubyOnRailsのポートフォリオを作りたかった
Webアプリケーション開発のフレームワークとしての知名度が高いRubyOnRailsの学習の成果として、
何かポートフォリオ作りてぇな...。と考えていたのですが、なかなかピンとくる題材がなく...。
(あんまり手の混んだやつは作るのがめんでぇぞ!の意)2.弟がHTMLの勉強を始めるにあたって何をしたらいいか聞いてきた
ある日弟が「HTMLの勉強をしたいのだが、まず何から手を付けたらよいのか?」と聞いてきました。
入門者向けのテキスト読んでもいいし、活字が苦手なやつだしドットインストールみたいなサイトで動画で動きを見ながらやったほうがいいかな...。
みたいなことを考えてHTML初学者が手を付けるべきサイトやテキストのAmazonのリンクに補足のコメントを付けてまとめていました。こんな感じの一言コメントを付けたリンク集を簡単に共有できるWebアプリとかねーかな...
そんな感じのコメント付きのリンク集を簡単にシェアできるWebアプリ...。
Railsのポートフォリオの題材としてちょうどいい...!という渡りに船な出来事があって、LinkSは誕生しました。(ガイドのお姉さん風)
これいる?
Q.(ブラウザがブックマークをクラウド管理してくれるこのご時世に)これいる?
文字制限があるTwitterで自分のオススメ〇〇集!みたいなのを共有したい人に需要があるかもしれない(希望的観測)
Q.(似たようなサービスがあるのに)これいる?
A.
(作ったのは)おれじゃない
(超エンジニア人の)あいつらがつくった
(おれはそんなサービス)しらない
(実装が)すんだこと
既に似たようなサービスがあることを気にしていたらポートフォリオなんて作れないんだよぉぉぉぉ!
開発中しょうもないミスで一時間くらい詰まっていた時、心の中で叫ぶセリフ第一位。使ったフレームワーク
RubyOnRails
説明不要のWebアプリケーションフレームワーク。
いずれRubyの仕事もしたいなーってことで勉強を始めたけど、ほんとに生産性上がってMAX大草原。
あんまりによかったのでRailsを参考にしているらしいPHPのLaravelも近々触ってみようかと思った(小並感)Haml
テンプレートエンジン。
Haml か Slimがよく採用されているらしいけど、なんとなくHamlを採用。
はじめは「書きにくいな...全部ERBで書いた後にerb2hamlでhamlに変換してやろうか...くそったれぇ...!(本末転倒)」なんてその気になっていたお前の姿はお笑いだったぜ。
慣れれば慣れるほどコードの見通しが良くなって、結果的に生産性向上に大きく貢献してくれました。Bootstrap
説明不要のCSSフレームワーク。
デザイン面がクソザコナメクジ過ぎていっつもこればっかり使っているので、今度違うWebアプリ作る時は頼らないで作りたい(猛省)jQuery
い つ も の (JavaScriptフレームワーク)
「まだオワコンフレームワーク使ってんのかよ?」と思った貴方。
いきなりvue.jsかよ。モダンッパリらしいな。世界最高フレームワークjQueryを侮辱した罪...軽くねーぜ?
ごめんなさい。慣れてるからっていっつもなんとなくで使っちゃうんです...。
jQueryからvue.jsのステップアップ記事とか見てると、凄い良さそうなんで今度使います...。
(すぐ使うとは言ってない)改修、機能追加したい部分
1. ブックマークのURL入力時に自動でページタイトルをスクレイピングして、タイトルの入力の手間軽減
クロスドメインでのスクレイピングを跨げるライブラリが利用しているYahoo!のYQLが完全に死んだらしく、
どうにかして実現できないかなと模索中。2. GoogleChromeの拡張機能で、ブラウザのブックマークからのインポート処理機能
そもそも普段使ってるブラウザのブックマークからインポートできたら一番ラクだよねってこと。
GoogleChrome拡張機能開発の勉強をやってみたいので、割とモチベ高し。3. SPA化
RailsをAPIモードにして、ページ表示はクライアントからAPIを叩くだけの構成を実装してみたい。
このアプリでは作り直すのがめんどくさいので多分やらない(屑)(ポートフォリオ作成を)完走した感想
まずRubyOnRailsの生産性の高さに驚きました。
使わなくても分かるシンプル構成のシステムなのもあり、ほとんどサーバ側のコードは書いてないです。
全体工数の7割はクライアント側のUI作成に時間が取られてます。...。
これもうRubyOnRailsのポートフォリオとして成立してるかわかんねぇな(屑)でもやっぱり設計、製造、テスト、リリース : 俺は気軽に色々やれて楽しいですね。
実務だとなかなかそうはいかないので、みんなも気軽にポートフォリオ作成して...見せ合いっこしよっ!!!
俺もやったんだからさ(同調圧力)あっ(唐突)、作業中に良さげな"おやつ"と"飲み物"があったら、コメント欄で教えてください。
LinkSで教えてくれたらもっと嬉しいです余談:他のおすすめリンク集
せっかく作ったアプリなので、他のぼくセレクトも公開します。
RubyOnRailsの学習に役立ったリンク集 by hassoubeat LinkS
RubyOnRailsの学習を始めるにあたって参考になったリンク集です。
おすすめゲームのPV集 by hassoubeat LinkS
ハードウェア問わずおすすめのゲーム集です。
落ち込んでいる時に元気が出る動画集 by hassoubeat LinkS
落ち込んでいる時に見ると元気を貰える動画集です。
※ ぼくセレクトなので、効果の保証はできません
- 投稿日:2019-04-15T20:05:58+09:00
【Rails】【ポートフォリオ】自作のブックマークシェアWebアプリで『作業が捗るおやつ・ドリンク集』を紹介します
オッス(Z戦士)
突然ですが、作業中の"おやつ"と"飲み物"って生きてく上での酸素と同じくらい大切だと思うんですよね。
ぼくは大量のコードと長時間向き合ってもビクともしない超(スーパー)エンジニア人ではないので、
作業中は仙豆に相当する"おやつ"と"飲み物"で都度回復しないと、「hassoubeat(ぼく)は置いてきた...ハッキリ言ってこれからの業務にはついていけない...」
といった具合に、天さん(上司)に見捨てられること請け合いです。
そんなぼくをギリギリ戦いに参加できるヤムチャレベルまで引き上げてくれるドーピングアイテム。それが、作業中の"おやつ"と"飲み物"なのです。
今回はそんなぼくが愛好する"おやつ"、"飲み物"を...
オラが作ったRailsのWebアプリで『作業が捗るおやつ・ドリンク集』をいっちょ紹介してみっか!!!(唐突)
作業が捗るおやつ・ドリンク集 by hassoubeat LinkS
赤枠の箇所をクリック・タッチしてもらえればブックマークに対して一言コメントが読めるゾ個人的に"きかんしゃトーマスとなかまたちチューイングキャンディ」と「マテ茶」は実力はあるのに、あまり知られていないのが残念で仕方ないです。
もし興味を持っていただけたら、リンク先からポチってお試しいただけると嬉しいです。
...。
Webアプリ側にコメントを書いているので当たり前なのですが、おやつに関して書くことがなくなってしまいました。このまま終わるのも寂しいという皆様のためにぃ(ねっとり)
ここから先は今回開発したWebアプリの話でもしようかと思います。
(おやつの話以外)興味ないね(魔晄中毒者)という方は、
オススメの"おやつ"と"飲み物"をコメントに書いてからブラウザバックしてもらえたら嬉しいゾ自作Webアプリの紹介
今回開発したWebアプリ『LinkS(リンクス)』の紹介にイクゾー!
そもそもこのアプリはなんなの?
コメントを付けたブックマーク集をワンクリックで公開してSNSにも簡単に共有できるブックマークシェアWebアプリです。
実際にシェアするまでの流れを見てもらいましょう。
1.フォルダー作成
ブックマークの公開・共有はフォルダー単位で行われるため、まずフォルダーを。
公開に設定しない限り、自分だけのブックマーク集としても利用できます。2.ブックマーク登録
さっき作ったフォルダーにブックマークを登録します。Just Monika.3.フォルダー公開
フォルダーの公開設定を公開に変更することで、ログインしている本人以外にもURLを叩けばそのフォルダーが見れるように。4.シェア
おすすめゲームのPV集 by hassoubeat LinkS
URLを直接シェアする以外にも、LinkSからSNSに直接シェアすることもできます。ちなみにスマホでもちゃんと使えます
...。
機能がシンプル過ぎるので、話すことがなくなりました。
一応申し訳程度にいいね機能、管理機能とかも実装してます。現在β版ですが、もし気になる人がいたら捨てアドでアカウント登録して使ってみてくれたら嬉しいゾ。
なんで作ろうと思い立ったワケ?
理由は2つありますねぇ!
1.RubyOnRailsのポートフォリオを作りたかった
2.弟がHTMLの勉強を始めるにあたって何をしたらいいか聞いてきた1.RubyOnRailsのポートフォリオを作りたかった
Webアプリケーション開発のフレームワークとしての知名度が高いRubyOnRailsの学習の成果として、
何かポートフォリオ作りてぇな...。と考えていたのですが、なかなかピンとくる題材がなく...。
(あんまり手の混んだやつは作るのがめんでぇぞ!の意)2.弟がHTMLの勉強を始めるにあたって何をしたらいいか聞いてきた
ある日弟が「HTMLの勉強をしたいのだが、まず何から手を付けたらよいのか?」と聞いてきました。
入門者向けのテキスト読んでもいいし、活字が苦手なやつだしドットインストールみたいなサイトで動画で動きを見ながらやったほうがいいかな...。
みたいなことを考えてHTML初学者が手を付けるべきサイトやテキストのAmazonのリンクに補足のコメントを付けてまとめていました。こんな感じの一言コメントを付けたリンク集を簡単に共有できるWebアプリとかねーかな...
そんな感じのコメント付きのリンク集を簡単にシェアできるWebアプリ...。
Railsのポートフォリオの題材としてちょうどいい...!という渡りに船な出来事があって、LinkSは誕生しました。(ガイドのお姉さん風)
これいる?
Q.(ブラウザがブックマークをクラウド管理してくれるこのご時世に)これいる?
文字制限があるTwitterで自分のオススメ〇〇集!みたいなのを共有したい人に需要があるかもしれない(希望的観測)
Q.(似たようなサービスがあるのに)これいる?
A.
(作ったのは)おれじゃない
(超エンジニア人の)あいつらがつくった
(おれはそんなサービス)しらない
(実装が)すんだこと
既に似たようなサービスがあることを気にしていたらポートフォリオなんて作れないんだよぉぉぉぉ!
開発中しょうもないミスで一時間くらい詰まっていた時、心の中で叫ぶセリフ第一位。使ったフレームワーク
RubyOnRails
説明不要のWebアプリケーションフレームワーク。
いずれRubyの仕事もしたいなーってことで勉強を始めたけど、ほんとに生産性上がってMAX大草原。
あんまりによかったのでRailsを参考にしているらしいPHPのLaravelも近々触ってみようかと思った(小並感)Haml
テンプレートエンジン。
Haml か Slimがよく採用されているらしいけど、なんとなくHamlを採用。
はじめは「書きにくいな...全部ERBで書いた後にerb2hamlでhamlに変換してやろうか...くそったれぇ...!(本末転倒)」なんてその気になっていたお前の姿はお笑いだったぜ。
慣れれば慣れるほどコードの見通しが良くなって、結果的に生産性向上に大きく貢献してくれました。Bootstrap
説明不要のCSSフレームワーク。
デザイン面がクソザコナメクジ過ぎていっつもこればっかり使っているので、今度違うWebアプリ作る時は頼らないで作りたい(猛省)jQuery
い つ も の (JavaScriptフレームワーク)
「まだオワコンフレームワーク使ってんのかよ?」と思った貴方。
いきなりvue.jsかよ。モダンッパリらしいな。世界最高フレームワークjQueryを侮辱した罪...軽くねーぜ?
ごめんなさい。慣れてるからっていっつもなんとなくで使っちゃうんです...。
jQueryからvue.jsのステップアップ記事とか見てると、凄い良さそうなんで今度使います...。
(すぐ使うとは言ってない)改修、機能追加したい部分
1. ブックマークのURL入力時に自動でページタイトルをスクレイピングして、タイトルの入力の手間軽減
クロスドメインでのスクレイピングを跨げるライブラリが利用しているYahoo!のYQLが完全に死んだらしく、
どうにかして実現できないかなと模索中。2. GoogleChromeの拡張機能で、ブラウザのブックマークからのインポート処理機能
そもそも普段使ってるブラウザのブックマークからインポートできたら一番ラクだよねってこと。
GoogleChrome拡張機能開発の勉強をやってみたいので、割とモチベ高し。3. SPA化
RailsをAPIモードにして、ページ表示はクライアントからAPIを叩くだけの構成を実装してみたい。
このアプリでは作り直すのがめんどくさいので多分やらない(屑)(ポートフォリオ作成を)完走した感想
まずRubyOnRailsの生産性の高さに驚きました。
使わなくても分かるシンプル構成のシステムなのもあり、ほとんどサーバ側のコードは書いてないです。
全体工数の7割はクライアント側のUI作成に時間が取られてます。...。
これもうRubyOnRailsのポートフォリオとして成立してるかわかんねぇな(屑)でもやっぱり設計、製造、テスト、リリース : 俺は気軽に色々やれて楽しいですね。
実務だとなかなかそうはいかないので、みんなも気軽にポートフォリオ作成して...見せ合いっこしよっ!!!
俺もやったんだからさ(同調圧力)あっ(唐突)、作業中に良さげな"おやつ"と"飲み物"があったら、コメント欄で教えてください。
LinkSで教えてくれたらもっと嬉しいです余談:他のおすすめリンク集
せっかく作ったアプリなので、他のぼくセレクトも公開します。
RubyOnRailsの学習に役立ったリンク集 by hassoubeat LinkS
RubyOnRailsの学習を始めるにあたって参考になったリンク集です。
おすすめゲームのPV集 by hassoubeat LinkS
ハードウェア問わずおすすめのゲーム集です。
落ち込んでいる時に元気が出る動画集 by hassoubeat LinkS
落ち込んでいる時に見ると元気を貰える動画集です。
※ ぼくセレクトなので、効果の保証はできません
- 投稿日:2019-04-15T18:45:44+09:00
【Rails】 flash時にメッセージにリンクを埋め込む
- 投稿日:2019-04-15T17:37:33+09:00
自己紹介
自己紹介
初めまして、本日4月15日に入社しました。
井上 雄貴
と申します。今回は五つ、自己紹介をしたいと思います。
- 出身地 大阪府生まれ大阪育ち。地元は大阪の北摂地域の豊中というところです。
- 生年月日 1994年6月4日生まれ、現在24歳。
- 前職 私は、前職警察官をしていました。大阪の住吉区の交番で勤務してました。
- 趣味 趣味は体を動かすことも好きですが、インドアな映画鑑賞、音楽鑑賞、大学時代にダンスミュージックにハマりDJをして簡単なMIXを作るのも大好きです。
- これからの目標 私にとって2社目のdivに入社し、divの方がたと一人でも多く、関係を築き、仲良くなることとすぐにでもdivに貢献できるように、仕事を頑張りたいと思っています。
- 投稿日:2019-04-15T14:31:55+09:00
where後に配列に入っている値をハッシュ形式にする方法。(レコード1件のみ時)
whereで値を取得した後は配列に入っています。
下記のコードですが、Entryモデル中の1つのroom_idには送信者、受信者のuser_idがある。
(1つのroom_idにつき最小、最大2名のみ)
したがって自分以外のuser_idを残すためにwhere.notで自分のuser_idを取得しないようにしている。@room_idには1つのuser_idしかないのがわかっている中で、
each文での取り出しはスマートではない。コード
28: @room_id = Entry.where(room_id: params[:id]).where.not(user_id: current_user.id) 29: @room_id.each do |user| 30: @reception_user = User.find(user.user_id) => 31: binding.pry 32: end 33: link "#{@reception_user.name}さんとのチャットルーム", user_room_path@room_idに入っている値です。
> @room_id => [#<Entry:0x00007ff76be33a40 id: 2, user_id: 2, room_id: 1,試したこと
配列からハッシュにするto_hメソッドを見つけて試したが、無理な様子。
@room_id = Entry.where(room_id: params[:id]).where.not(user_id: current_user.id) @room = @room_id.to_hエラー内容
wrong element type Entry (expected array)解決法
レコードが1件しかないのがわかっているので、firstで配列を展開から展開されハッシュ形式で@entryに渡っている。
@room_id = Entry.where(room_id: params[:id]).where.not(user_id: current_user.id).first
- 投稿日:2019-04-15T14:01:55+09:00
case文での条件分岐方法
滞在しているページごとにサイドバーに表示させるリストの内容を変更したかったので
if文を使い行っていたが、条件が多くなるに連れて可読性が悪くなってきたため、
case文でコードを書き直したが条件分岐が行われなかった。if文でviewに書いたコード
- if params[:controller] == 'users' && params[:action] == 'show'case文を使い書き直したコード
- case params[:controller] - when 'users' && params[:action] == 'show'teratailで質問し解決したのでメモ。
https://teratail.com/questions/184492
下記のようにすることでコントローラーのアクションごとに異なるviewの切り替えを実現できた。- case params.values_at :controller, :action - when ['rooms', 'show']
- 投稿日:2019-04-15T12:33:21+09:00
delayed_job再起動手順
ローカル開発環境でdelayed_jobを利用してメール送信などの実装をしている場合、delayed_jobが起動していないせいでメールが確認できないということがある。
そのような場合はdelayed_jobを再起動してあげる必要がある。### delayed_jobの再起動 $ bin/delayed_job restartなお、キューがたくさん溜まっているとdelayed_jobを再起動したタイミングで一気にメールが飛ぶので、全部削除しておくとよい
$ bundle exec rails c ### 現在溜まっているジョブ数の確認 pry(main)> Delayed::Job.count ### キューの削除 pry(main)> Delayed::Job.delete_all
- 投稿日:2019-04-15T12:24:51+09:00
Payjpに登録したクレジットカードで商品購入を実装する(Rails)
この記事を読む前に
↓前回の投稿内容が実施されていることを前提に記載しています。
Payjpでクレジットカード登録と削除機能を実装する(Rails)実装する機能と前提条件
Payjp(Pay.jp)から既に顧客IDとカードIDを取得済みでの購入を想定しています。
実装するものとしては下記のとおりです。
- 自作のカード登録フォーム(前回)
- カード情報とユーザーの紐づけ(前回)
- ユーザーとカードの登録と削除(前回)
- 商品の購入(←今回)
バージョン情報
ruby 2.3.1
Rails 5.0.7前提条件
- deviseが導入済みでログインができている(current_userを使うため)
- hamlでの記載(gem 'haml-rails')
- payjpのアカウントが既に取得できていて、ユーザーとカードの登録が完了している(前回実施)
- cardテーブルに以下の情報が登録されている(前回実施)
- user_id → UserテーブルのID
- customer_id → payjpの顧客ID
- card_id → payjpのデフォルトカードID
顧客IDとデフォルトカードIDは以下の画面で顧客ごとに確認できます。
もしDBを作成していなかったり可動しなかったりする場合はID直打ちでトライしてみましょう。
顧客詳細確認画面
1.コントローラーを作成しよう
app/controllers/purchase_controller.rbclass PurchaseController < ApplicationController require 'payjp' def index card = Card.where(user_id: current_user.id).first #Cardテーブルは前回記事で作成、テーブルからpayjpの顧客IDを検索 if card.blank? #登録された情報がない場合にカード登録画面に移動 redirect_to controller: "card", action: "new" else Payjp.api_key = ENV["PAYJP_PRIVATE_KEY"] #保管した顧客IDでpayjpから情報取得 customer = Payjp::Customer.retrieve(card.customer_id) #保管したカードIDでpayjpから情報取得、カード情報表示のためインスタンス変数に代入 @default_card_information = customer.cards.retrieve(card.card_id) end end def pay card = Card.where(user_id: current_user.id).first Payjp.api_key = ENV['PAYJP_PRIVATE_KEY'] Payjp::Charge.create( :amount => 13500, #支払金額を入力(itemテーブル等に紐づけても良い) :customer => card.customer_id, #顧客ID :currency => 'jpy', #日本円 ) redirect_to action: 'done' #完了画面に移動 end end2.購入画面と完了画面を作成しよう
購入画面
app/views/purchase/index.html.haml%h2 購入を確定しますか? %p Apple MacBook Pro 13インチ %p ¥135,000(送料込み) %br %h3 支払い方法 - if @default_card_information.blank? %br / - else -#以下カード情報を表示 = "**** **** **** " + @default_card_information.last4 - exp_month = @default_card_information.exp_month.to_s - exp_year = @default_card_information.exp_year.to_s.slice(2,3) = exp_month + " / " + exp_year %br = form_tag(action: :pay, method: :post) do %button 購入する
ちなみにexp_monthはカードの期限月、exp_yearは期限年、last4はカードの下4桁を取得します。
https://pay.jp/docs/api/#顧客のカード情報を取得完了画面
app/views/purchase/done.html.haml%h2 購入が完了しました! %p Apple MacBook Pro 13インチ %p ¥135,000(送料込み)3.ルートを設定しよう
config/routes.rb#今回設定分 get 'purchase', to: 'purchase#index' post 'purchase/pay', to: 'purchase#pay' get 'purchase/done', to: 'purchase#done'本当に購入されているのだろうか…
実装はこれで完了です!
画面変遷はできてても登録ができているか不安な場合は
売上一覧の画面で確認できます!
参考
- 投稿日:2019-04-15T10:58:15+09:00
DB中間テーブルについて
中間テーブルについて簡単に説明!
中間テーブルが必要になるのはアソシエーションを考えるときに多対多になったときに便宜上必要なテーブルです。
なのでhas_many:テーブル名,through中間テーブル名
でアソシエーションを組むこと。
また、DBにテーブルを作る。
そして、便宜上作ったものなので、大元の多対多のアソシエーションをhas_manyで組むことも忘れずに行う。
- 投稿日:2019-04-15T10:35:03+09:00
Example of using defaultdict to prevent KeyError in # python's nested dictionary (#ruby comparison)
example
- Nesting and using defaultdict in layers
- I can not get angry if I write a nonexistent key like
d["x"]["y"]["z"]
- Maybe a good girl may not be imitating
>>> from collections import defaultdict >>> d = defaultdict(lambda: defaultdict(lambda: defaultdict(lambda: 0))) >>> d["a"]["b"]["c"] = 1 >>> d["a"]["b"]["c"] 1 >>> d["x"]["y"]["z"] 0If you write in ruby
It was such a feeling. This is also a good girl.
[27] pry(main)> h = Hash.new(Hash.new(Hash.new(0))) => {} [28] pry(main)> h["a"]["b"]["c"] = 1 => 1 [29] pry(main)> h["a"]["b"]["c"] => 1 [30] pry(main)> h["x"]["y"]["z"] => 0ref
How to use Python defaultdict-Qiita
Original by Github issue
- 投稿日:2019-04-15T10:34:07+09:00
単語集計 awk, ruby
プログラミング言語AWK
https://www.amazon.co.jp/dp/4901280406に掲載の単語集計プログラムを利用してきた。
wc.awk{ gsub(/[`'&%$-.,:;!?^*_~=|@\\\#<>(){}0123456789\[\]"]/," ") for (i=1;i<=NF;i++) count[$i]++ } END {for (w in count) print w,count[w] | "sort -f" }上記プログラムは、trコマンドで大文字を小文字に変換してあることを前提としている。
$ tr 'a-z' 'A-Z' < infile > outfile $ awk -f wc.awk infule > out filetrコマンドでの大文字化(小文字化)
https://qiita.com/Lewuathe/items/4370be45f5d49c5bf72bwc2.awk
https://researchmap.jp/jomd7nobo-45644/?lang=japanesewc2.awk# Print list of word frequencies # 単語の出現頻度のリストを出力する。 { $0 = tolower($0) # 大小文字の区別をなくす gsub(/[^a-z_ \t]/, " ", $0) # 句読点をとる for (i = 1; i <= NF; i++) freq[$i]++ } END { for (word in freq) printf "%s\t%d\n", word, freq[word] }$ awk -f wc2.awk infule > out fileあ、こっちsortしてなかった。
表計算ソフトに読み込んでsortおよび管理。ruby
単語頻度を数える
https://sites.google.com/site/rubycocoamemo/Home/ruby-guan-lian/tango-hindo-wo-kazoeruwc.rb#!/usr/bin/ruby # Word Counter for source code in programming language without comment or standard document without 0C . # ver.0.1 2014.12.29, # ver.0.2 2014.12.29, # ver.0.3 2014.12.30 standard I/O # ver.0.4 2015.4.13 downcase # https://sites.google.com/site/rubycocoamemo/Home/ruby-guan-lian/tango-hindo-wo-kazoeru # Eddited by Dr. OGAWA Kiyoshi words = Hash.new(0) while buf = STDIN.gets break if buf.chomp == "exit" buf.downcase.scan(/\w+/) do |word| words[word] += 1 end end print "WORD\tCOUNT\n" words.sort_by{|word,count| [-count,word]}.each do |word,count| print "#{word}\t#{count}\n" end p.s. 20170709追記 chmod 0777 wc.rb ./wc.rb pcd2.txt ./wc.rb: line 11: syntax error near unexpected token `(' ./wc.rb: line 11: `words = Hash.new(0)' p.s. 2017 f = open('sample.txt') data = f.read() # counting words = {} for word in data.split(): words[word] = words.get(word, 0) + 1 # sort by count d = [(v,k) for k,v in words.items()] d.sort() d.reverse() for count, word in d[:1000]: print count, word参考資料
英語論文・規格・特許を読むときの作業記録
https://researchmap.jp/jorteykhj-51292/GCC コメント除去、単語計算
https://researchmap.jp/joo4thhg9-1778110/
- 投稿日:2019-04-15T10:09:04+09:00
#python の ネストされた辞書で KeyError を起こさないように defaultdict を利用する例 ( #ruby 比較 )
example
- defaultdict を何層にもネストして使ってみる
d["x"]["y"]["z"]
のように存在しないキーを書いても怒られない- もしかしたら良い子は真似しちゃダメかもしれない
>>> from collections import defaultdict >>> d = defaultdict(lambda: defaultdict(lambda: defaultdict(lambda: 0))) >>> d["a"]["b"]["c"] = 1 >>> d["a"]["b"]["c"] 1 >>> d["x"]["y"]["z"] 0ruby で書くなら
こんな感じだったかな。こちらも良い子はマネし‥。
[27] pry(main)> h = Hash.new(Hash.new(Hash.new(0))) => {} [28] pry(main)> h["a"]["b"]["c"] = 1 => 1 [29] pry(main)> h["a"]["b"]["c"] => 1 [30] pry(main)> h["x"]["y"]["z"] => 0ref
Python defaultdict の使い方 - Qiita
Original by Github issue
- 投稿日:2019-04-15T10:07:21+09:00
Railsの勉強を初めて、基本的な内容をメモ
はじめに
rails tutorialを終えて、整理するためにアウトプットします。
Qiitaに投稿するのも初めてなので、Markdownもよくわかりませんが、練習して見ようと思います。アプリケーション作成
rails _5.1.6_ new app1.「5.1.6」はバージョン
2.「app」はアプリ名Gemfileを修正して「bundle install」を実行し、gemをインストール
(Gemfileの内容は今後理解する必要あり)
エラーになった場合は「bundle update」する必要あり
(エラーのログに記載されている)ローカル環境にインストールしないようにするためには下記の特殊なフラグを使用する
(HerokuでSQLiteはサポートされていないため、必要になるみたいだがよくわからない)bundle install --without productionHeroku CLIのインストール(Herokuのコマンドラインインターフェイスを利用可能にする)
$ source <(curl -sL https://cdn.learnenough.com/heroku_install)正しくインストールされたかは下記コマンドを実行
$ heroku --versionherokuに新しいアプリケーションの実行場所を作成する
$ heroku creategit&heroku コマンド
$ git add -A $ git commit -m "コミットのメッセージ" $ git checkout master $ git merge 「ブランチ名」 $ git push $ git push heroku $ rails db:migrate $ heroku pg:reset DATABASE $ heroku run rails db:migrate $ heroku run rails db:seed $ heroku restartRails コマンド
フォルダやファイルの自動生成
home_controller.rb
がapp/controllers
に生成され、このファイルの中身にtopメソッドがある
generateはgに省略が可能$ rails generate controller home top
config/routes.rb
内で「get "URL", to: 'コントローラ名#アクション名'」を記述することでtop.html.erb
の内容がブラウザで表示可能get 'home/top', to: 'home#top'アクションの追加方法
generateは生成するという意味なので
rails g ~
は使えません
ルーティングを追加し、アクションを追加する必要があります。routes.rbにルーティングの設定
get 'about', to: 'home#about'
home_controller.rb
にアクションの追加def about endビューを追加
app/views/home
にabout.html.erb
を追加初期表示の変更
ルートURLを設定
root 'コントローラ名#アクション名'コード
繰り返し処理
<% オブジェクト.each do |変数| %> <% end %>link_toメソッド
リンクをメソッド
<%= link_to "リンクの名前", URLまたはルーティングヘルパー %>findメソッド
引数に
id
の値を指定することでそのid
のレコードを取得する
Postテーブルの2レコード目を取得post = Post.find(2)redirect_toメソッド
更新処理等でページを移動する場合に使用
リダイレクトするときはpath
ではなくurl
を使用するredirect ヘルパー名_urlDB
データベースの操作
テーブル作成
マイレグレーションファイルを作成
$ rails g model Post content:textPost・・・テーブル(モデルは単数形)
content:text・・・「カラム名:データ型」ルーティングの確認方法
1.ターミナル
$ rails routers
2.ブラウザ
ブラウザのアドレスの末尾に/rails/info
と入力
- 投稿日:2019-04-15T08:21:49+09:00
No route matches [DELETE] "/users/sign_out" エラー(Rails)
はじめに
初学者の学習アウトプット用記事です。
ご指摘訂正アドバイスは是非お願いします。で、今回のテーマは!!!!!!
エラー!!!!です。
内容としては、deviseでログイン機能を実装してログインはできるのにログアウトするとエラーが起きてしまうということでした。
No route matches [DELETE] "/users/sign_out"
エラー文が
No route matches [DELETE] "/users/sign_out"
なんとなくなんですが、
「DELETEのルーティングされてねぇぞ!!ごらぁああ!!!!」
と言われてる気がしました。
ターミナルにてrake routesコマンド実行してみると、
destroy_user_session GET /users/sign_out(.:format) devise/sessions#destroy #メソッドがGETになってる???ビューファイルのログアウトボタンのリンクのパスは問題なく記述できてました。
sign_outログアウトのメソッドってDELETEじゃないの???????ってことでルーティング確認!!
routes.rbRails.application.routes.draw do devise_for :users root 'groups#index' resources :users, only: [:index,:edit, :update] resources :groups, only: [:new, :create, :edit, :update] do resources :messages, only: [:index, :create] end endあれ???問題なくね????
どこがおかしいんだ?・・・・・
ってことでメンターさんに質問。
メンターさんも??????あれ????なんだろう???とrake routesで確認。
するとやはりGETになってる。試しにroutes.rbファイルのdevise_for :usersの記述を削除
routes.rbRails.application.routes.draw do root 'groups#index' resources :users, only: [:index,:edit, :update] resources :groups, only: [:new, :create, :edit, :update] do resources :messages, only: [:index, :create] end endそしてターミナルでrake routesコマンド!!!!
すると!!!!!
destroy_user_session DELETE /users/sign_out(.:format) devise/sessions#destroyGETがDELETEに変わってる!!!!
そのまま再度、devise_for :usersを記述。
routes.rbRails.application.routes.draw do devise_for :users root 'groups#index' resources :users, only: [:index,:edit, :update] resources :groups, only: [:new, :create, :edit, :update] do resources :messages, only: [:index, :create] end endそんで再度ターミナルでrake routesで確認したらDELETEになっていました。
無事、その後rails sでサーバー再起動させたら問題なくログアウトできました。
とりあえず解決はできたのですが、
今回の件はバグ?みたいなものと説明されましたが真相は謎です。他にも
記事を調べたら
[Rails 4.x] Devise で Sign Out が Routing Error になる際の対応。(method の delete が get になる場合)
https://qiita.com/colorrabbit/items/5545fce7e5cd4e494396の記事がでてきました。
上記の記事の内容を試したのですがこちらは特に変化がなくエラーのままでした。
- 投稿日:2019-04-15T07:32:49+09:00
【Rails】find_or_initialize_byメソッドを使ってインスタンスを作成する時のポイント
現在、amazonAPIを利用した口コミの共有サービスを作成中です。
その中で、「商品を検索し表示させる」という処理があるのですが、その際に役立った
find_or_initialize_by
メソッドについて簡単に整理します。
- 参考記事 Railsガイド
find_or_initialize_byメソッドとは
find_or_initialize_byメソッド
とは、条件に合致したインスタンスがデータベースに保存されているかどうかをチェックしています。この際、
- データベースに保存されている場合は
find
メソッド- データベースに保存されていない場合は'new'メソッド
として、インスタンスの状況によって適用されるメソッドが異なることがポイントです。インスタンスが保存されている場合、findメソッドが適用されるのでインスタンスに保存済みのデータ(idなど)を含めることができます。
インスタンス = persisted?
やインスタンス = new_record?
でデータベースの保存状況を真偽値で取得できます。find_or_initialize_byメソッドの使い道
前述の通り、
find_or_initialize_by
は条件分岐がポイントとなるので、データベースの保存状況でインスタンスに変化を与えたい場合に有用となります。例えば私の場合ですと、APIから商品データを取得し一覧表示しています。
その際に、データベース保存済みなら「商品削除ボタン」を表示、データベースに保存していない新規のインスタンスなら「商品登録ボタン」を表示したいケースで、
find_or_initialize_by
を使用しています。products_controller.rbdef create @product = Product.find_or_initialize_by(asin: params[:product_asin]) unless @product.persisted? # @product が保存されていない場合、先に @product を保存する products = Amazon::Ecs.item_lookup( params[:product_asin], response_group: 'Medium', country: 'jp' ) products.items.each do |item| @product = Product.new( title: item.get('ItemAttributes/Title'), image_url: item.get('LargeImage/URL'), url: item.get('DetailPageURL'), asin: item.get('ASIN'), brand_amazon_name: item.get('ItemAttributes/Brand'), price: item.get('OfferSummary/LowestNewPrice/Amount'), ) @product.save end end end_products.html.erb<!--商品登録削除ボタン--> <div class="buttons text-center"> <% if product.persisted? %> <%= form_tag(product_path(product.id), method: :delete) do %> <%= hidden_field_tag :product_id, product.id %> <%= submit_tag '削除', class: 'btn btn-danger' %> <% end %> <% else %> <%= form_tag(products_path) do %> <%= hidden_field_tag :product_asin, product.asin %> <%= submit_tag '登録', class: 'btn btn-primary' %> <% end %> <% end %>(+α)find_or_create_byメソッドについて
find_or_create_by
メソッドは、find_or_initialize_by
と似た内容のメソッドなので、今後のために簡単に整理。条件に合致したインスタンスがデータベースに保存されているかどうかをチェックしている点は、両者とも同じです。
その際に、
find_or_create_by
メソッドは、
- データベースに保存されている場合は
find
メソッド- データベースに保存されていない場合は'create'メソッド
となることがポイントです。「データベースに保存されていない場合は'create'メソッド」となるのですね。
条件に合致した情報をゴリゴリとデータベースに保存していくというケースに適しているのでしょう。
まとめ
find_or_initialize_byメソッドは、「APIを利用して情報取得→整形しインスタンス作成」のようなケースで役立つことがわかりました。
- 投稿日:2019-04-15T03:11:22+09:00
はてなブックマーク Web APIを手軽に使えるgemを作った
手元のMacがなくなってSwiftが書けなくなったので、新しいMacが届くまでの間、空いた時間にはてなブックマークのWeb APIを気軽に扱えるgemを作ってみました。
Nabeatsu/hatena_bookmark_client_for_ruby: API Client of Hatena bookmark for Ruby
はてなブックマークAtomAPIに対応したgem kkosuge/hatena-bookmarkが既に公開されているのですが、既にサポートが終了されています。
はてなブックマークAtom APIのサポートを終了します - はてなブックマーク開発ブログ
プライベートで開発中のはてなブックマークのサードパーティクライアントではてなブックマークのAPIやフィードの仕様にある程度慣れていたので、今回Rubyで現在ドキュメントに公開されているAPIに対応したライブラリを作りました。
基本的な使い方
APIごとにサンプルを書きます。各インスタンスメソッドの返り値は
Net::HTTPResponse
のサブクラスで、リクエストに成功した場合bodyプロパティがJSONとして解釈できるようになっています。require 'json' JSON.parse(hatebu.get.body) # {"http://b.hatena.ne.jp/"=>7372, "http://www.hatena.ne.jp/"=>5621}はてなブックマーク REST API
仕様:はてなブックマーク REST API - Hatena Developer Center
OAuthによるユーザー認証
はてなブックマーク REST APIはOAuthによるユーザー認証が必要になります
仕様:Consumer key を取得して OAuth 開発をはじめよう - Hatena Developer Center開発者向け設定ページからアプリケーションを登録したら取得できるconsumer keyとconsumer secretを使ってOAuth認証を行いaccess tokenとaccess token secretを取得しないと一部APIにアクセス出来ないので事前に取得しておきましょう。
今回作ったgemをinstallすると手元で動作確認できるようにaccess tokenとaccess token secretを取得出来るコマンドが使えるので面倒なら使ってみてください。引数にconsumer keyとconsumer secretを必要とします。渡さずに実行すると使い方を説明する文字列が出力されます。
$ get_hatebu_access_token Usage: ruby get_access_token.rb <consumer key> <consumer secret>
ブックマークの作成
require "hatena_bookmark_client_for_ruby" hatebu = HatenaBookmarkClient::Bookmark.new( consumer_key: CONSUMER_KEY, consumer_secret: CONSUMER_SECRET, request_token: REQUEST_TOKEN, request_secret: REQUEST_SECRET, ) body = { url: "https://www.google.com/", comment: "test", } response = hatebu.create(body) puts response.bodyブックマークの削除
hatebu.delete("https://www.google.com/")ブックマーク情報の取得
hatebu.get("https://www.google.com/")ブックマーク一覧から検索
これははてなブックマーク REST APIではなく、マイブックマーク全文検索APIなのですが、OAuth認証をしていればリクエストを投げれるのでここで紹介します。
response = hatebu.search("id", "hatena")はてなブックマーク件数取得API
仕様:はてなブックマーク件数取得API - Hatena Developer Center
仕様どおり50個まで配列にブックマーク件数を取得したいURLを追加出来ます。
count = HatenaBookmarkClient::BookmarkCount.new(["http://www.hatena.ne.jp/", "http://b.hatena.ne.jp/"]) count.get # {"http://www.hatena.ne.jp/":5790,"http://b.hatena.ne.jp/":6793}はてなブックマークエントリー情報
仕様:はてなブックマークエントリー情報取得API - Hatena Developer Center
エントリー情報を取得したいURLを引数に渡します。
entry = HatenaBookmarkClient::Entry.new("http://www.hatena.ne.jp/") entry.get.body # 関連記事を取得しない高速なレスポンスで返却するAPIへのリクエスト entry.get_withou_relations他にもブックマークされたエントリーの情報を取得するエントリーAPI、ユーザーのタグ情報を取得するタグAPI、OAuth 認証したユーザーの情報を取得するユーザー情報APIなどへのリクエストができます。
今後の予定
現在
- はてなブックマーク REST API
- はてなブックマーク件数取得API
- はてなブックマークエントリー情報取得API
- マイブックマーク全文検索APIのすべてに対応しているのですが、マイブックマーク全文検索APIで利用できる認証(OAuth認証、WSSE認証、およびCookie認証)のうち、OAuth認証のみに対応しているので他の認証にも対応させる予定です。
対応予定
- はてなスターAPI
- はてなブックマークフィードはてなブックマークフィードはAPIではないのですが、はてなブックマークのコンテンツを利用するサービスを作る際に利用することが多いと考えられるのと、実際に自分が使いたいので対応させる予定です。
初めてgemを作ってみた感想。
単機能なgemを作るだけなら作成から公開までかなり簡単に行えました。 一度作ると他の人のgemも読みやすくなり、参考に出来るところも増えて良いことしかなかったです。
gemを作る際に参考にした記事
【Ruby】gemの作り方から公開まで - Qiita
Gemの作り方まとめ 普通のgem編 - masarakki's blog
gemを作る時に気をつけていること - くりにっき
橋本商会 » Bundlerとgem.dependencyの順序
- 投稿日:2019-04-15T03:09:45+09:00
Ruby on Rails: Google Mapをレスポンシブに対応する
実現したいこと
Wepアプリ開発していると、Google mapを使う時があるかと思います。
そんな時に、ただただマップコードを埋め込むとせっかくのレスポンシブデザインを意識したサイトが崩れてしまいます。
なので、今回はレスポンシブデザインに対応させる方法を共有したいと思う。解決方法
<iframe>
を<div class="gmap">
でカッコって上げることで解決できる。<div class="gmap"><%== @user.map %></div>.gmap{ position: relative; padding-bottom: 56.25%; padding-top: 30px; height: 0; overflow: hidden; } .gmap iframe, .gmap object, .gmap embed { position: absolute; top: 0; left: 0; width: 100%; height: 100%;
- 投稿日:2019-04-15T02:59:09+09:00
macOS Mojave, Nokogiriインストールできない問題 解決メモ
macOS MojaveでNokogiriがインストールできない問題解消のメモ
概要
macOSのアップデート後から、Nokogiri Gemのインストールが痛恨の失敗!!
初心者の私には正直理解不能だったが頑張ってエラーを見てググる、を繰り返してみた。
発生したエラー
" clang -o conftest -I/Users/user_name/.rbenv/versions/2.6.2/include/ruby-2.6.0/x86_64-darwin17 -I/Users/user_name/.rbenv/versions/2.6.2/include/ruby-2.6.0/ruby/backward -I/Users/user_name/.rbenv/versions/2.6.2/include/ruby-2.6.0 -I. -I/Users/user_name/Desktop/app/app/vendor/bundler/ruby/2.6.0/gems/nokogiri-1.10.2/ports/x86_64-apple-darwin17.7.0/libxslt/1.1.33/include -I/Users/user_name/Desktop/app/app/vendor/bundler/ruby/2.6.0/gems/nokogiri-1.10.2/ports/x86_64-apple-darwin17.7.0/libxml2/2.9.9/include/libxml2 -I/Users/user_name/Desktop/app/app/vendor/bundler/ruby/2.6.0/gems/nokogiri-1.10.2/ports/x86_64-apple-darwin17.7.0/libxml2/2.9.9/include/libxml2 -I/Users/user_name/.rbenv/versions/2.6.2/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -D_DARWIN_UNLIMITED_SELECT -D_REENTRANT "-DNOKOGIRI_LIBXML2_PATH=\"/Users/user_name/Desktop/app/app/vendor/bundler/ruby/2.6.0/gems/nokogiri-1.10.2/ports/x86_64-apple-darwin17.7.0/libxml2/2.9.9\"" "-DNOKOGIRI_LIBXML2_PATCHES=\"0001-Revert-Do-not-URI-escape-in-server-side-includes.patch 0002-Remove-script-macro-support.patch 0003-Update-entities-to-remove-handling-of-ssi.patch\"" "-DNOKOGIRI_LIBXSLT_PATH=\"/Users/user_name/Desktop/app/app/vendor/bundler/ruby/2.6.0/gems/nokogiri-1.10.2/ports/x86_64-apple-darwin17.7.0/libxslt/1.1.33\"" "-DNOKOGIRI_LIBXSLT_PATCHES=\"\"" -O3 -Wno-error=shorten-64-to-32 -pipe -I /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/libxml2 -DNOKOGIRI_USE_PACKAGED_LIBRARIES conftest.c -L. -L/Users/user_name/.rbenv/versions/2.6.2/lib -L/Users/user_name/Desktop/app/app/vendor/bundler/ruby/2.6.0/gems/nokogiri-1.10.2/ports/x86_64-apple-darwin17.7.0/libxml2/2.9.9/lib -L/Users/user_name/Desktop/app/app/vendor/bundler/ruby/2.6.0/gems/nokogiri-1.10.2/ports/x86_64-apple-darwin17.7.0/libxslt/1.1.33/lib -L/usr/local/Cellar/xz/5.2.4/lib -L. -L/Users/user_name/.rbenv/versions/2.6.2/lib -fstack-protector-strong -L/usr/local/lib/Users/user_name/Desktop/app/app/vendor/bundler/ruby/2.6.0/gems/nokogiri-1.10.2/ports/x86_64-apple-darwin17.7.0/libxslt/1.1.33/lib/libexslt.a -lm -liconv -lpthread -llzma -lz /Users/user_name/Desktop/app/app/vendor/bundler/ruby/2.6.0/gems/nokogiri-1.10.2/ports/x86_64-apple-darwin17.7.0/libxml2/2.9.9/lib/libxml2.a/Users/user_name/Desktop/app/app/vendor/bundler/ruby/2.6.0/gems/nokogiri-1.10.2/ports/x86_64-apple-darwin17.7.0/libxslt/1.1.33/lib/libxslt.a -lm -liconv -lpthread -llzma -lz /Users/user_name/Desktop/app/app/vendor/bundler/ruby/2.6.0/gems/nokogiri-1.10.2/ports/x86_64-apple-darwin17.7.0/libxml2/2.9.9/lib/libxml2.a -llzma -lruby.2.6-static -framework Security -framework Foundation -lpthread -ldl -lobjc /Users/user_name/Desktop/app/app/vendor/bundler/ruby/2.6.0/gems/nokogiri-1.10.2/ports/x86_64-apple-darwin17.7.0/libxslt/1.1.33/lib/libexslt.a -lm -liconv -lpthread -llzma -lz /Users/user_name/Desktop/app/app/vendor/bundler/ruby/2.6.0/gems/nokogiri-1.10.2/ports/x86_64-apple-darwin17.7.0/libxml2/2.9.9/lib/libxml2.a /Users/user_name/Desktop/app/app/vendor/bundler/ruby/2.6.0/gems/nokogiri-1.10.2/ports/x86_64-apple-darwin17.7.0/libxslt/1.1.33/lib/libxslt.a -lm -liconv -lpthread -llzma -lz /Users/user_name/Desktop/app/app/vendor/bundler/ruby/2.6.0/gems/nokogiri-1.10.2/ports/x86_64-apple-darwin17.7.0/libxml2/2.9.9/lib/libxml2.a -llzma " checked program was: /* begin */ 1: #include "ruby.h" 2: 3: /*top*/ 4: extern int t(void); 5: int main(int argc, char **argv) 6: { 7: if (argc > 1000000) { 8: int (* volatile tp)(void)=(int (*)(void))&t; 9: printf("%d", (*tp)()); 10: } 11: 12: return 0; 13: } 14: extern void xmlSchemaSetParserStructuredErrors(); 15: int t(void) { xmlSchemaSetParserStructuredErrors(); return 0; } /* end */解決方法
bundle configでビルド時のオプションとして、
--use-system-libraries
と--with-xml2-include
を設定しておくといいらしい!$ bundle config build.nokogiri --use-system-libraries --with-xml2-include=$(brew --prefix libxml2)/include/libxml2解決しました!
参考
An error occurred while installing nokogiri (1.10.0), and Bundler cannot continue.
- 投稿日:2019-04-15T01:57:05+09:00
気付いたこと備忘録
- 投稿日:2019-04-15T01:43:52+09:00
Payjpでクレジットカード登録と削除機能を実装する(Rails)
実装する機能と前提条件
今回、Payjp(Pay.jp)を利用して入力フォームを直接ページ内に設置します。
実装するものとしては下記のとおりです。
- 自作のカード情報入力フォーム
- カード情報とユーザーの紐づけ
- ユーザーとカードの登録と削除
- 商品の購入(次回の記事参照)
もしSDKを使う場合は別記事をご覧いただくかPAY.JP API 利用ガイド | PAY.JPを触るとイメージをつかみやすいと思います。
バージョン情報
・ruby 2.3.1
・Rails 5.0.7前提条件
・deviseが導入済みでログインができている(current_userを使うため)
・hamlでの記載(gem 'haml-rails')1.Payjpのアカウントを作成しよう
Payjpのサイトでアカウントを作成します。
2.APIを確認しよう
ダッシュボードのAPIより確認ができます。
今回はテストモードでの実装なので、テスト秘密鍵とテスト公開鍵を使用します。
3.payjpのgemを設置しよう
下記をgemfileに記載しbandle installを実施します。
gem 'payjp'4.payjp.jsを読み込めるようにしよう
下記の通りに追記します。
app/views/layouts/application.html.haml%html %head %meta{:content => "text/html; charset=UTF-8", "http-equiv" => "Content-Type"}/ %title payjptest %script{src: "https://js.pay.jp/", type: "text/javascript"} -# このscriptを記載 = csrf_meta_tags = stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' = javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %body = yield5.データベースを作成しよう
下記内容でpayjpのデータを保管するデータベースを作成します。nullはお好みで。
尚、紐づけは以下のとおりです。
- user_id -> Userテーブルのid
- customer_id -> payjpの顧客id
- card_id -> payjpのデフォルトカードid
(デフォルトカードidはトークンとは違います。ここの理解で結構時間をとってしまいました…)db/migrate/20190400000000_create_cards.rbclass CreateCards < ActiveRecord::Migration[5.0] def change create_table :cards do |t| t.integer :user_id, null: false t.string :customer_id, null: false t.string :card_id, null: false t.timestamps end end endちなみにカード情報そのものを保存することは禁止されていますので、
payjpに保管されている情報を顧客idやカードidで呼び出すことで情報取得や支払いなどに対応します。
カード情報非通過化対応のお願い6.コントローラーを作成しよう
下記内容でコントローラーを作成します。
ENV["PAYJP_PRIVATE_KEY"]は環境変数でテスト秘密鍵を設定し読み込みます。
私はdotenvを利用しています。app/controllers/card_controller.rbclass CardController < ApplicationController require "payjp" def new card = Card.where(user_id: current_user.id) redirect_to action: "show" if card.exists? end def pay #payjpとCardのデータベース作成を実施します。 Payjp.api_key = ENV["PAYJP_PRIVATE_KEY"] if params['payjp-token'].blank? redirect_to action: "new" else customer = Payjp::Customer.create( description: '登録テスト', #なくてもOK email: current_user.email, #なくてもOK card: params['payjp-token'], metadata: {user_id: current_user.id} ) #念の為metadataにuser_idを入れましたがなくてもOK @card = Card.new(user_id: current_user.id, customer_id: customer.id, card_id: customer.default_card) if @card.save redirect_to action: "show" else redirect_to action: "pay" end end end def delete #PayjpとCardデータベースを削除します card = Card.where(user_id: current_user.id).first if card.blank? else Payjp.api_key = ENV["PAYJP_PRIVATE_KEY"] customer = Payjp::Customer.retrieve(card.customer_id) customer.delete card.delete end redirect_to action: "new" end def show #Cardのデータpayjpに送り情報を取り出します card = Card.where(user_id: current_user.id).first if card.blank? redirect_to action: "new" else Payjp.api_key = ENV["PAYJP_PRIVATE_KEY"] customer = Payjp::Customer.retrieve(card.customer_id) @default_card_information = customer.cards.retrieve(card.card_id) end end end7.カードの登録画面を作成しよう
今回は登録画面と確認兼削除画面の2つを作成します。デザインはアレンジしてください。
登録画面
app/view/card/new.html.haml= form_tag(card_pay_path, method: :post, id: 'charge-form', name: "inputForm") do %label カード番号 = text_field_tag "number", "", class: "number", placeholder: "半角数字のみ" ,maxlength: "16", type: "text", id: "card_number" %br %label 有効期限 %select#exp_month{name: "exp_month", type: "text"} %option{value: ""} -- %option{value: "1"}01 %option{value: "2"}02 %option{value: "3"}03 %option{value: "4"}04 %option{value: "5"}05 %option{value: "6"}06 %option{value: "7"}07 %option{value: "8"}08 %option{value: "9"}09 %option{value: "10"}10 %option{value: "11"}11 %option{value: "12"}12 %span 月/ %select#exp_year{name: "exp_year", type: "text"} %option{value: ""} -- %option{value: "2019"}19 %option{value: "2020"}20 %option{value: "2021"}21 %option{value: "2022"}22 %option{value: "2023"}23 %option{value: "2024"}24 %option{value: "2025"}25 %option{value: "2026"}26 %option{value: "2027"}27 %option{value: "2028"}28 %option{value: "2029"}29 %span 年 %br %label セキュリティコード = text_field_tag "cvc", "", class: "cvc", placeholder: "カード背面3~4桁の番号", maxlength: "4", id: "cvc" #card_token = submit_tag "追加する", id: "token_submit"最初、= sectionを使っていたのですがうまく行かなかったため
%optionが連続発生し駄長なコードになっているのはご了承ください…確認兼削除画面
app/view/card/show.html.haml%label 登録クレジットカード情報 %br = "**** **** **** " + @default_card_information.last4 %br - exp_month = @default_card_information.exp_month.to_s - exp_year = @default_card_information.exp_year.to_s.slice(2,3) = exp_month + " / " + exp_year = form_tag(card_delete_path, method: :post, id: 'charge-form', name: "inputForm") do %input{ type: "hidden", name: "card_id", value: "" } %button 削除する8.Payjpにデータを送りトークンを取得しよう
提供されているpay.jpのサンプルを参照し一部アレンジしております。
app/assets/javascripts/payjp.jsdocument.addEventListener( "DOMContentLoaded", e => { Payjp.setPublicKey("pk_test_79ae2d2743199a76f3ebbbbb"); //ここに公開鍵を直書き let btn = document.getElementById("token_submit"); //IDがtoken_submitの場合に取得されます btn.addEventListener("click", e => { //ボタンが押されたときに作動します e.preventDefault(); //ボタンを一旦無効化します let card = { number: document.getElementById("card_number").value, cvc: document.getElementById("cvc").value, exp_month: document.getElementById("exp_month").value, exp_year: document.getElementById("exp_year").value }; //入力されたデータを取得します。 Payjp.createToken(card, (status, respnse) => { if (status === 200) { //成功した場合 $("#card_number").removeAttr("name"); $("#cvc").removeAttr("name"); $("#exp_month").removeAttr("name"); $("#exp_year").removeAttr("name"); //データを自サーバにpostしないように削除 $("#card_token").append( $('<input type="hidden" name="payjp-token">').val(response.id) ); //取得したトークンを送信できる状態にします document.inputForm.submit(); alert("登録が完了しました"); //確認用 } else { alert("カード情報が正しくありません。"); //確認用 } }); }); }, false );9.ルートを作成しよう
今回はshow,pay,new,deleteの4つのメゾットがあるので下記の通り追記します。
一部はresoursesで設定してもよいかと思います。config/routes.rbpost 'card/new', to: 'card#new' post 'card/show', to: 'card#show' post 'card/pay', to: 'card#pay' post 'card/delete', to: 'card#delete'10.カードを登録してみよう
テストカードはこちらです。
それ以外を打ち込んだ場合はトークンが発行できずはねられます。
以上でカード登録から削除まで一通り実装できました。
次回はこれを使って商品支払いを実装します。参考
- 投稿日:2019-04-15T00:26:55+09:00
Railsでデプロイする際に躓いた箇所
Railsでデプロイする際に躓いた箇所がいくつか(というより沢山)あったので自分用メモも兼ねて書きます。
secret_key_base周り
Rails5.2からsecrets.ymlの代わりにcredentials.yml.encが生成されるようになりました。
rails newされると自動でapp/configにcredentials.yml.encとmaster.keyが生成されます。
master.keyが無い状態でrails credentials:editコマンドを実行するとmaster.keyが生成されますが、生成されたmaster.keyで復号できず困りました。Rails 5.2 で ActiveSupport::MessageEncryptor::InvalidMessage
こちらの記事にある通り、ローカルにあるmaster.keyの中身をコピーしてproduction環境のmaster.keyに貼り付けたところいけました。
MySQLでAccess denied
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)このようなエラーが出てきて入れず。
どうやら自動で仮パスワードが発行されているようなので調べてみると、
cat /var/log/mysqld.log | grep password 2019-04-14T11:01:59.067618Z 1 [Note] A temporary password is generated for root@localhost: **********となっていたのでこちらの仮パスワードで無事いけました。
Unicornが起動できない
Unicornを起動しようとしたところ以下のようなエラーが。
master failed to start, check stderr log for detailslog/unicorn.logをチェックしたところ、
/home/fkdolly/.rbenv/versions/2.3.3/lib/ruby/gems/2.3.0/gems/unicorn-5.5.0/lib/unicorn.rb:49:in `block in builder': wrong number of arguments (given 0, expected 2) (ArgumentError)調べてみるとUnicorn 5.5.0で出ているエラーのようでした。
Unicorn で Rails アプリが起動しなかったので対処
Unicorn Refreshing Gem Listbundle exec gem list | grep unicorn unicorn (5.5.0)同じく5.5.0でしたので、
Gemfilegroup :production, :staging do gem 'unicorn', '5.4.1' endbundle installこれでいけるかなと思ったらまだエラー。
5.5.0を削除するのを忘れていました。bundle exec gem uninstall unicorn -v '5.5.0' bundle updateこれで無事に起動できました。