20190415のRubyに関する記事は26件です。

model内のインスタンスメソッドの中でインスタンスの属性値を取得する

経緯

  • 自分が書いた過去のコード(Ruby書き始めだった頃のもの)を見ていると、「今はとりあえずこのようにしか書けないけど、本当はもっとよりよく書けるはずだ」と思っていた部分が目に入ったので、直します。
  • 表題の件について、誰か同じように詰まった方の参考になれればいいのですが。。。

修正前

  • 以下のようなコードです。しかしすごい書き方していますね。。。
game.rb
  def get_gameset_msg
    gameset_msg = "試合中"
    if self[:gameset_flag]
      gameset_msg = "試合終了"
    end
    return gameset_msg
  end

修正後

  • カラム名は修正していませんが、「gameset_flag」は「is_gameset」とかの方がいいんでしょうか。。。
game.rb
  def get_gameset_msg
    self.gameset_flag ? "試合終了" : "試合中"
  end

ポイント

  • 基本的な取得方法(修正後と同じコード)
    • model内のインスタンスメソッドの中では、selfでインスタンス本体を指します。self.xxxで属性値を取得できます。(こういう書き方って、あんまり載ってない気がするのですが。。。)
game.rb
  def get_gameset_msg
    self.gameset_flag ? "試合終了" : "試合中"
  end
  • 属性名を動的に生成する場合
    • イニングごとの得点を合計した値が欲しい場合などは、動的にカラム名を生成することでコード量を減らせますが、この場合はハッシュのvalueを取得するように書きます。self.xxxのようには書けません。
game.rb
  def 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.rb
  def 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

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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_login
config/routes.rb
  Rails.application.routes.draw do
    root 'home#top'
    get 'home/after_login'
  end
Gemfile
  ...追記
  gem 'devise'
$ bundle
$ rails g devise:install
$ rails g devise User
$ rails db:migrate
app/views/home/top.html.erb
  <%= link_to '新規登録', new_user_registration_path %>
  <%= link_to 'ログイン', new_user_session_path %>
app/controllers/application_controller.rb
  class ApplicationController < ActionController::Base

    def after_sign_in_path_for(resource)
      home_after_login_path
    end
  end
app/views/home/after_login.html.erb
  <%= link_to "ログアウト", destroy_user_session_path, method: :delete %>

name, email, passwordで新規登録、name, passwordでログインする機能の作成

  1. nameカラムの作成 & emailのバリデーション系を全て外す
$ rails g migration AddNameToUsers name:string
$ rails g migration ChangeColumnToUsers
$ rails g migration remove_index_email_from_users
db/migrate/日時_change_column_to_users.rb
  class 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
  end
db/migrate/日時_remove_index_email_from_users.rb
  class RemoveIndexEmailFromUsers < ActiveRecord::Migration[5.2]
    def change
      remove_index :users, column: :email, unique: true
    end
  end
$ rails db:migrate
config/initializers/devise.rb
  ...編集
  config.authentication_keys = [:name]
app/models/user.rb
  ...追記
  def email_required?
    false
  end
  def email_changed?
    false
  end
  1. 新規登録フォーム, ログインフォームの編集
$ rails g devise:views
app/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>
  1. パラメータの許可
app/controllers/application_controller.rb
  class 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

以上。

完成コード

devise_name

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[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_login
config/routes.rb
  Rails.application.routes.draw do
    root 'home#top'
    get 'home/after_login'
  end
Gemfile
  ...追記
  gem 'devise'
$ bundle
$ rails g devise:install
$ rails g devise User
$ rails db:migrate
app/views/home/top.html.erb
  <%= link_to '新規登録', new_user_registration_path %>
  <%= link_to 'ログイン', new_user_session_path %>
app/controllers/application_controller.rb
  class ApplicationController < ActionController::Base

    def after_sign_in_path_for(resource)
      home_after_login_path
    end
  end
app/views/home/after_login.html.erb
  <%= link_to "ログアウト", destroy_user_session_path, method: :delete %>

name, email, passwordで新規登録、name, passwordでログインする機能の作成

  1. nameカラムの作成 & emailのバリデーション系を全て外す
$ rails g migration AddNameToUsers name:string
$ rails g migration ChangeColumnToUsers
$ rails g migration remove_index_email_from_users
db/migrate/日時_change_column_to_users.rb
  class 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
  end
db/migrate/日時_remove_index_email_from_users.rb
  class RemoveIndexEmailFromUsers < ActiveRecord::Migration[5.2]
    def change
      remove_index :users, column: :email, unique: true
    end
  end
$ rails db:migrate
config/initializers/devise.rb
  ...編集
  config.authentication_keys = [:name]
app/models/user.rb
  ...追記
  def email_required?
    false
  end
  def email_changed?
    false
  end
  1. 新規登録フォーム, ログインフォームの編集
$ rails g devise:views
app/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>
  1. パラメータの許可
app/controllers/application_controller.rb
  class 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

以上。

完成コード

devise_name

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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:migrate

resetのコード入力後、再度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
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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 stop

webrickも試してみます。

$ 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

せっかくなので、 thinfalcon も試してみます。 Gemfile に thinfalcon を追加します。

Gemfile
gem '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 もそのまま使えるとわかったのは収穫でした。

参考情報

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】オラ自作のブックマークシェアWebアプリで『作業が捗るおやつ・ドリンク集』を紹介すっぞ!

オッス(Z戦士)

突然ですが、作業中の"おやつ"と"飲み物"って生きてく上での酸素と同じくらい大切だと思うんですよね。


(おやつを食べると思わず)笑っちゃうんすよね。

ぼくは大量のコードと長時間向き合ってもビクともしない超(スーパー)エンジニア人ではないので、
作業中は仙豆に相当する"おやつ"と"飲み物"で都度回復しないと、

「hassoubeat(ぼく)は置いてきた...ハッキリ言ってこれからの業務にはついていけない...」

tyaozu.gif
餃子かわいそう。

といった具合に、天さん(上司)に見捨てられること請け合いです。
そんなぼくをギリギリ戦いに参加できるヤムチャレベルまで引き上げてくれるドーピングアイテム。

それが、作業中の"おやつ"と"飲み物"なのです。

今回はそんなぼくが愛好する"おやつ"、"飲み物"を...

オラが作ったRailsのWebアプリで『作業が捗るおやつ・ドリンク集』をいっちょ紹介してみっか!!!(唐突)

作業が捗るおやつ・ドリンク集 by hassoubeat LinkS


赤枠の箇所をクリック・タッチしてもらえればブックマークに対して一言コメントが読めるゾ

個人的に"きかんしゃトーマスとなかまたちチューイングキャンディ」と「マテ茶」は実力はあるのに、あまり知られていないのが残念で仕方ないです。
もし興味を持っていただけたら、リンク先からポチってお試しいただけると嬉しいです。






...。
Webアプリ側にコメントを書いているので当たり前なのですが、おやつに関して書くことがなくなってしまいました。

このまま終わるのも寂しいという皆様のためにぃ(ねっとり)


ここから先は今回開発したWebアプリの話でもしようかと思います。


(おやつの話以外)興味ないね(魔晄中毒者)という方は、
オススメの"おやつ"と"飲み物"をコメントに書いてからブラウザバックしてもらえたら嬉しいゾ

cloud.jpeg
FF7リメイクはいつ...?

自作Webアプリの紹介

今回開発したWebアプリ『LinkS(リンクス)』の紹介にイクゾー!

LinkS_login.png
安直なネーミング恥ずかしくないのかよ

そもそもこのアプリはなんなの?

コメントを付けたブックマーク集をワンクリックで公開してSNSにも簡単に共有できるブックマークシェアWebアプリです。

yaruo2.png

実際にシェアするまでの流れを見てもらいましょう。

1.フォルダー作成
LinkS_create_folder.png
ブックマークの公開・共有はフォルダー単位で行われるため、まずフォルダーを。
公開に設定しない限り、自分だけのブックマーク集としても利用できます。

2.ブックマーク登録
LinkS_create_link.png
さっき作ったフォルダーにブックマークを登録します。Just Monika.

3.フォルダー公開
LinkS_folder_edit.png
フォルダーの公開設定を公開に変更することで、ログインしている本人以外にもURLを叩けばそのフォルダーが見れるように。

4.シェア
LinkS_share_line.png
LinkS_share_twitter.png
おすすめゲームのPV集 by hassoubeat LinkS
URLを直接シェアする以外にも、LinkSからSNSに直接シェアすることもできます。

ちなみにスマホでもちゃんと使えます

LinkS_sm_login.png LinkS_sm_sidebar.png LinkS_sm_TOP.png

...。
機能がシンプル過ぎるので、話すことがなくなりました。
一応申し訳程度にいいね機能、管理機能とかも実装してます。

現在β版ですが、もし気になる人がいたら捨てアドでアカウント登録して使ってみてくれたら嬉しいゾ。

なんで作ろうと思い立ったワケ?

理由は2つありますねぇ!

1.RubyOnRailsのポートフォリオを作りたかった
2.弟がHTMLの勉強を始めるにあたって何をしたらいいか聞いてきた

1.RubyOnRailsのポートフォリオを作りたかった

Webアプリケーション開発のフレームワークとしての知名度が高いRubyOnRailsの学習の成果として、
何かポートフォリオ作りてぇな...。と考えていたのですが、なかなかピンとくる題材がなく...
(あんまり手の混んだやつは作るのがめんでぇぞ!の意)

2.弟がHTMLの勉強を始めるにあたって何をしたらいいか聞いてきた

ある日弟が「HTMLの勉強をしたいのだが、まず何から手を付けたらよいのか?」と聞いてきました。
入門者向けのテキスト読んでもいいし、活字が苦手なやつだしドットインストールみたいなサイトで動画で動きを見ながらやったほうがいいかな...。
みたいなことを考えてHTML初学者が手を付けるべきサイトやテキストのAmazonのリンクに補足のコメントを付けてまとめていました。

こんな感じの一言コメントを付けたリンク集を簡単に共有できるWebアプリとかねーかな...

amro.jpeg
この感覚...!残業か!!!

そんな感じのコメント付きのリンク集を簡単にシェアできるWebアプリ...。
Railsのポートフォリオの題材としてちょうどいい...!

という渡りに船な出来事があって、LinkSは誕生しました。(ガイドのお姉さん風)

これいる?

Q.(ブラウザがブックマークをクラウド管理してくれるこのご時世に)これいる?

A.
yaruo.jpg

文字制限があるTwitterで自分のオススメ〇〇集!みたいなのを共有したい人に需要があるかもしれない(希望的観測)

Q.(似たようなサービスがあるのに)これいる?

A.
(作ったのは)おれじゃない
(超エンジニア人の)あいつらがつくった
(おれはそんなサービス)しらない
(実装が)すんだこと



既に似たようなサービスがあることを気にしていたらポートフォリオなんて作れないんだよぉぉぉぉ!


vegita.png
開発中しょうもないミスで一時間くらい詰まっていた時、心の中で叫ぶセリフ第一位。

使ったフレームワーク

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

落ち込んでいる時に見ると元気を貰える動画集です。
※ ぼくセレクトなので、効果の保証はできません

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】【ポートフォリオ】自作のブックマークシェアWebアプリで『作業が捗るおやつ・ドリンク集』を紹介します

オッス(Z戦士)

突然ですが、作業中の"おやつ"と"飲み物"って生きてく上での酸素と同じくらい大切だと思うんですよね。


(おやつを食べると思わず)笑っちゃうんすよね。

ぼくは大量のコードと長時間向き合ってもビクともしない超(スーパー)エンジニア人ではないので、
作業中は仙豆に相当する"おやつ"と"飲み物"で都度回復しないと、

「hassoubeat(ぼく)は置いてきた...ハッキリ言ってこれからの業務にはついていけない...」

tyaozu.gif
餃子かわいそう。

といった具合に、天さん(上司)に見捨てられること請け合いです。
そんなぼくをギリギリ戦いに参加できるヤムチャレベルまで引き上げてくれるドーピングアイテム。

それが、作業中の"おやつ"と"飲み物"なのです。

今回はそんなぼくが愛好する"おやつ"、"飲み物"を...

オラが作ったRailsのWebアプリで『作業が捗るおやつ・ドリンク集』をいっちょ紹介してみっか!!!(唐突)

作業が捗るおやつ・ドリンク集 by hassoubeat LinkS


赤枠の箇所をクリック・タッチしてもらえればブックマークに対して一言コメントが読めるゾ

個人的に"きかんしゃトーマスとなかまたちチューイングキャンディ」と「マテ茶」は実力はあるのに、あまり知られていないのが残念で仕方ないです。
もし興味を持っていただけたら、リンク先からポチってお試しいただけると嬉しいです。






...。
Webアプリ側にコメントを書いているので当たり前なのですが、おやつに関して書くことがなくなってしまいました。

このまま終わるのも寂しいという皆様のためにぃ(ねっとり)


ここから先は今回開発したWebアプリの話でもしようかと思います。


(おやつの話以外)興味ないね(魔晄中毒者)という方は、
オススメの"おやつ"と"飲み物"をコメントに書いてからブラウザバックしてもらえたら嬉しいゾ

cloud.jpeg
FF7リメイクはいつ...?

自作Webアプリの紹介

今回開発したWebアプリ『LinkS(リンクス)』の紹介にイクゾー!

LinkS_login.png
安直なネーミング恥ずかしくないのかよ

そもそもこのアプリはなんなの?

コメントを付けたブックマーク集をワンクリックで公開してSNSにも簡単に共有できるブックマークシェアWebアプリです。

yaruo2.png

実際にシェアするまでの流れを見てもらいましょう。

1.フォルダー作成
LinkS_create_folder.png
ブックマークの公開・共有はフォルダー単位で行われるため、まずフォルダーを。
公開に設定しない限り、自分だけのブックマーク集としても利用できます。

2.ブックマーク登録
LinkS_create_link.png
さっき作ったフォルダーにブックマークを登録します。Just Monika.

3.フォルダー公開
LinkS_folder_edit.png
フォルダーの公開設定を公開に変更することで、ログインしている本人以外にもURLを叩けばそのフォルダーが見れるように。

4.シェア
LinkS_share_line.png
LinkS_share_twitter.png
おすすめゲームのPV集 by hassoubeat LinkS
URLを直接シェアする以外にも、LinkSからSNSに直接シェアすることもできます。

ちなみにスマホでもちゃんと使えます

LinkS_sm_login.png LinkS_sm_sidebar.png LinkS_sm_TOP.png

...。
機能がシンプル過ぎるので、話すことがなくなりました。
一応申し訳程度にいいね機能、管理機能とかも実装してます。

現在β版ですが、もし気になる人がいたら捨てアドでアカウント登録して使ってみてくれたら嬉しいゾ。

なんで作ろうと思い立ったワケ?

理由は2つありますねぇ!

1.RubyOnRailsのポートフォリオを作りたかった
2.弟がHTMLの勉強を始めるにあたって何をしたらいいか聞いてきた

1.RubyOnRailsのポートフォリオを作りたかった

Webアプリケーション開発のフレームワークとしての知名度が高いRubyOnRailsの学習の成果として、
何かポートフォリオ作りてぇな...。と考えていたのですが、なかなかピンとくる題材がなく...
(あんまり手の混んだやつは作るのがめんでぇぞ!の意)

2.弟がHTMLの勉強を始めるにあたって何をしたらいいか聞いてきた

ある日弟が「HTMLの勉強をしたいのだが、まず何から手を付けたらよいのか?」と聞いてきました。
入門者向けのテキスト読んでもいいし、活字が苦手なやつだしドットインストールみたいなサイトで動画で動きを見ながらやったほうがいいかな...。
みたいなことを考えてHTML初学者が手を付けるべきサイトやテキストのAmazonのリンクに補足のコメントを付けてまとめていました。

こんな感じの一言コメントを付けたリンク集を簡単に共有できるWebアプリとかねーかな...

amro.jpeg
この感覚...!残業か!!!

そんな感じのコメント付きのリンク集を簡単にシェアできるWebアプリ...。
Railsのポートフォリオの題材としてちょうどいい...!

という渡りに船な出来事があって、LinkSは誕生しました。(ガイドのお姉さん風)

これいる?

Q.(ブラウザがブックマークをクラウド管理してくれるこのご時世に)これいる?

A.
yaruo.jpg

文字制限があるTwitterで自分のオススメ〇〇集!みたいなのを共有したい人に需要があるかもしれない(希望的観測)

Q.(似たようなサービスがあるのに)これいる?

A.
(作ったのは)おれじゃない
(超エンジニア人の)あいつらがつくった
(おれはそんなサービス)しらない
(実装が)すんだこと



既に似たようなサービスがあることを気にしていたらポートフォリオなんて作れないんだよぉぉぉぉ!


vegita.png
開発中しょうもないミスで一時間くらい詰まっていた時、心の中で叫ぶセリフ第一位。

使ったフレームワーク

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

落ち込んでいる時に見ると元気を貰える動画集です。
※ ぼくセレクトなので、効果の保証はできません

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】 flash時にメッセージにリンクを埋め込む

flashで通知させるときにどうすれば文字列にリンクを貼るのか悩んだので書きます。

html_safeを使う

html_safeを使えば解決します。

if @user.save
  link = "<a href=#{edit_user_path(:id)}>こちら</a>"
  flash[:success] = "ユーザー登録に成功しました。変更は#{link}でできます。".html_safe
  redirect_to user_path
end

「こちら」がURLになってますね。
html_safeを末尾に記入すれば解決!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

自己紹介

自己紹介

初めまして、本日4月15日に入社しました。
    井上 雄貴
と申します。今回は五つ、自己紹介をしたいと思います。

  • 出身地 大阪府生まれ大阪育ち。地元は大阪の北摂地域の豊中というところです。
  • 生年月日 1994年6月4日生まれ、現在24歳。
  • 前職 私は、前職警察官をしていました。大阪の住吉区の交番で勤務してました。
  • 趣味 趣味は体を動かすことも好きですが、インドアな映画鑑賞、音楽鑑賞、大学時代にダンスミュージックにハマりDJをして簡単なMIXを作るのも大好きです。
  • これからの目標 私にとって2社目のdivに入社し、divの方がたと一人でも多く、関係を築き、仲良くなることとすぐにでもdivに貢献できるように、仕事を頑張りたいと思っています。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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']
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Payjpに登録したクレジットカードで商品購入を実装する(Rails)

この記事を読む前に

↓前回の投稿内容が実施されていることを前提に記載しています。
Payjpでクレジットカード登録と削除機能を実装する(Rails)

実装する機能と前提条件

Payjp(Pay.jp)から既に顧客IDとカードIDを取得済みでの購入を想定しています。
実装するものとしては下記のとおりです。

  • 自作のカード登録フォーム(前回)
  • カード情報とユーザーの紐づけ(前回)
  • ユーザーとカードの登録と削除(前回)
  • 商品の購入(←今回)

「購入する」ボタンを押して購入!
image.png

バージョン情報

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直打ちでトライしてみましょう。
顧客詳細確認画面
image.png

1.コントローラーを作成しよう

app/controllers/purchase_controller.rb
class 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

end

2.購入画面と完了画面を作成しよう

購入画面
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 購入する

image.png
ちなみに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(送料込み)

image.png

3.ルートを設定しよう

config/routes.rb
  #今回設定分
  get 'purchase', to: 'purchase#index'
  post 'purchase/pay', to: 'purchase#pay'
  get 'purchase/done', to: 'purchase#done'

本当に購入されているのだろうか…

実装はこれで完了です!
画面変遷はできてても登録ができているか不安な場合は
売上一覧の画面で確認できます!
image.png

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

DB中間テーブルについて

中間テーブルについて簡単に説明!

中間テーブルが必要になるのはアソシエーションを考えるときに多対多になったときに便宜上必要なテーブルです。
なのでhas_many:テーブル名,through中間テーブル名
でアソシエーションを組むこと。
また、DBにテーブルを作る。
そして、便宜上作ったものなので、大元の多対多のアソシエーションをhas_manyで組むことも忘れずに行う。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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"] 
 0 
 

If 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"] 
 => 0 
 

ref

How to use Python defaultdict-Qiita

Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/1285

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

単語集計 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 file

trコマンドでの大文字化(小文字化)
https://qiita.com/Lewuathe/items/4370be45f5d49c5bf72b

wc2.awk
https://researchmap.jp/jomd7nobo-45644/?lang=japanese

wc2.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-kazoeru

wc.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/

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

#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"]
0

ruby で書くなら

こんな感じだったかな。こちらも良い子はマネし‥。

[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"]
=> 0

ref

Python defaultdict の使い方 - Qiita

Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/1284

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Railsの勉強を初めて、基本的な内容をメモ

はじめに

rails tutorialを終えて、整理するためにアウトプットします。
Qiitaに投稿するのも初めてなので、Markdownもよくわかりませんが、練習して見ようと思います。

アプリケーション作成

rails _5.1.6_ new app

1.「5.1.6」はバージョン
2.「app」はアプリ名

Gemfileを修正して「bundle install」を実行し、gemをインストール
(Gemfileの内容は今後理解する必要あり)
エラーになった場合は「bundle update」する必要あり
(エラーのログに記載されている)

ローカル環境にインストールしないようにするためには下記の特殊なフラグを使用する
(HerokuでSQLiteはサポートされていないため、必要になるみたいだがよくわからない)

bundle install --without production

Heroku CLIのインストール(Herokuのコマンドラインインターフェイスを利用可能にする)

$ source <(curl -sL https://cdn.learnenough.com/heroku_install)

正しくインストールされたかは下記コマンドを実行

$ heroku --version

herokuに新しいアプリケーションの実行場所を作成する

$ heroku create

git&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 restart

Rails コマンド

フォルダやファイルの自動生成

home_controller.rbapp/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/homeabout.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 ヘルパー名_url

DB

データベースの操作

テーブル作成

マイレグレーションファイルを作成

$ rails g model Post content:text

Post・・・テーブル(モデルは単数形)
content:text・・・「カラム名:データ型」

ルーティングの確認方法

1.ターミナル
$ rails routers
2.ブラウザ
ブラウザのアドレスの末尾に/rails/infoと入力

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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.rb
Rails.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.rb
Rails.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#destroy

GETがDELETEに変わってる!!!!

そのまま再度、devise_for :usersを記述。

routes.rb
Rails.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

の記事がでてきました。
上記の記事の内容を試したのですがこちらは特に変化がなくエラーのままでした。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】find_or_initialize_byメソッドを使ってインスタンスを作成する時のポイント

現在、amazonAPIを利用した口コミの共有サービスを作成中です。

その中で、「商品を検索し表示させる」という処理があるのですが、その際に役立ったfind_or_initialize_byメソッドについて簡単に整理します。

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.rb
def 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を利用して情報取得→整形しインスタンス作成」のようなケースで役立つことがわかりました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

はてなブックマーク 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の順序

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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%;
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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.

nokogiriが(また)インストールできない

macOS SierraでNokogiriがインストールできない問題の解決方法

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

気付いたこと備忘録

気付いたこと備忘録

ひたすら気付いたことをいったん書きなぐる記事

AWSCloud9関連

gitの変更内容はなぜか、runを押さないと反映されない。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Payjpでクレジットカード登録と削除機能を実装する(Rails)

実装する機能と前提条件

今回、Payjp(Pay.jp)を利用して入力フォームを直接ページ内に設置します。
実装するものとしては下記のとおりです。

  • 自作のカード情報入力フォーム
  • カード情報とユーザーの紐づけ
  • ユーザーとカードの登録と削除
  • 商品の購入次回の記事参照

イメージとしてはこんな感じの入力フォームです。
image.png

もし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より確認ができます。
今回はテストモードでの実装なので、テスト秘密鍵テスト公開鍵を使用します。
スクリーンショット 2019-04-14 16.31.04.png

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
    = yield

5.データベースを作成しよう

下記内容でpayjpのデータを保管するデータベースを作成します。nullはお好みで。
尚、紐づけは以下のとおりです。
- user_id -> Userテーブルのid
- customer_id -> payjpの顧客id
- card_id -> payjpのデフォルトカードid
(デフォルトカードidはトークンとは違います。ここの理解で結構時間をとってしまいました…)

db/migrate/20190400000000_create_cards.rb
class 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.rb
class 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
end

7.カードの登録画面を作成しよう

今回は登録画面と確認兼削除画面の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"

image.png

最初、= 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 削除する

image.png

8.Payjpにデータを送りトークンを取得しよう

提供されているpay.jpのサンプルを参照し一部アレンジしております。

app/assets/javascripts/payjp.js
document.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.rb
  post 'card/new', to: 'card#new'
  post 'card/show', to: 'card#show'
  post 'card/pay', to: 'card#pay'
  post 'card/delete', to: 'card#delete'

10.カードを登録してみよう

テストカードはこちらです。
それ以外を打ち込んだ場合はトークンが発行できずはねられます。
image.png

以上でカード登録から削除まで一通り実装できました。
次回はこれを使って商品支払いを実装します。

参考

https://pay.jp/docs/api/?ruby

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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)

このようなエラーが出てきて入れず。

mysql5.7でパスワードを変更する

どうやら自動で仮パスワードが発行されているようなので調べてみると、

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 details

log/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 List

bundle exec gem list | grep unicorn
unicorn (5.5.0)

同じく5.5.0でしたので、

Gemfile
group :production, :staging do
    gem 'unicorn', '5.4.1'
end
bundle install

これでいけるかなと思ったらまだエラー。
5.5.0を削除するのを忘れていました。

bundle exec gem uninstall unicorn -v '5.5.0'
bundle update

これで無事に起動できました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む