- 投稿日:2019-08-22T23:41:51+09:00
登録メール自動送信機能の実装
ユーザー登録時などに自動でメールを送る機能を実装しました。
ログイン機能のあるアプリ、Webサービスで登録すると自動でメールが来る、ユーザーにとっては鬱陶しい機能を実装してみました。
これを見る誰かの参考になれば幸いです。まずAction Maileの準備
メール送信機能の実装に先立ちまして、必要な準備があります。
以下development.rbの変更 変更後はpumaの再起動が必要です。development.rbconfig.action_mailer.delivery_method = :smtp config.action_mailer.raise_delivery_errors = true config.action_mailer.smtp_settings = { address: 'smtp.gmail.com', port: 587, user_name: 'gmailアドレス', password: 'googleアカウントのパスワード', authentication: 'plain' }delivery_methodはメールを送信する方法を指定しています。
raise_delivery_errorsはメール送信失敗時にエラーを発生させるかを指定しています。
smtp_settingで:smtpの設定情報を設定します。
address: はgmailを使って送信する場合はsmtp.gmail.com
softbankならsmtp.softbank.comのように変わります。詳しくは調べてみてください。これにて事前準備は完了です。
メーラーを作成する
$ rails g mailer sample sendmail_confilmsampleメーラーにsendmail_confilmメソッドを作成
メーラーを編集
sample_mailer.rbを編集する
sample_mailer.rbdefault from: 'sample@gmail.com' def sendmail_confirm(user) @user = user mail to: user.email, subject: 'ユーザー登録ありがとうございます' #これが件名 endsendmail_confirmがコントローラーで言う所のアクションに当たります。
sendmail_confirm.html.erbを呼んできます。
またはsendmail_confirm.text.erbメールの編集
sendmail_confilm.html.erb任意のメールの内容メーラーを呼び出すためのアクションを作成する
メーラーはクライアントからのアクションを直接受け取れませんのでアクションを作成します。
mail_controller.rbdef sendmail user = User.find(id) @mail = SampleMailer.sendmail_confirm(user).deliver_now #① render plain: ’送信完了’①の文 メーラー名.メソッド()でメーラーを呼び出せます。
メールを送ってみる
以上でメールを送る準備が完了しました。
ブラウザで〜/sample/sendmail_confirm
にアクセスして送信完了です。アプリに実装する時はメールを送りたい時にメーラーを呼び出すようにコードを書くだけです。
終わり
わかりにくい部分などもあったかもしれませんが最後までお読みいただきありがとうございました。
この記事に誤りや改善点などございましたら編集リクエストにてご指摘いただけると幸いです。
- 投稿日:2019-08-22T22:36:23+09:00
AutomationObject Ruby Gem for UI Automation Published
AutomationObject Ruby gem is a YAML configuration based dynamic DSL framework for UI automation using Selenium or Appium drivers.
Gem Purpose:
The purpose of this gem was to provide a layer in between the drivers I commonly used and my Cucumber testing suite. Using YAML configurations to define and map the UI, this gem enables the creation of a dynamic DSL framework reflecting the configuration that allows automation to occur through the provided DSL API.
Reason for Creating:
Working as a QA developer in Test, I was having a hard time figuring out how I could scale up our testing codebase. I had an idea which included using configurations to define UI automation behavior and combine that with Ruby’s super sweet meta programming (reflection) abilities to create a dynamic DSL framework that controls the UI automation. Using the DSL framework which represented the UI I wanted to automate, I could issue commands to the framework and keep the complexities of UI automation hidden from the rest of the codebase.
The hope was that the codebase growth would be limited to the YAML configurations and cucumber features, and nowhere else. With the proper organization of the YAML configuration files, I could continue to grow those configurations and have legacy versions stored too. Using stateless step definitions, I wouldn’t have continual growth in that part of the codebase. Then finally, cucumber features that would test specific sites that can write my essay online or apps using specific YAML configurations would be the only other part to grow.
Example YAML Configuration File:
qiita.rbbase_url: 'http://www.spartzinc.com' default_screen: 'home_screen' screens: home_screen: elements: team_link: css: '#path div.to #element' click: after: change_screen: 'team_screen' team_screen: before_load: wait_for_elements: - element_name: 'title' exists?: true visible?: true text: 'Meet Our Team' elements: title: xpath: '//path/to/element'Example Ruby File:
qiita.rbrequire 'automation_object' require 'selenium-webdriver' #New Selenium Driver driver = Selenium::WebDriver.for :chrome #Will load split up YAML files and return them merged into one Hash object blue_prints = AutomationObject::BluePrint.new('/file/path/containing/yaml/files') #Create the DSL framework automation_object = AutomationObject::Framework.new(driver, blue_prints) #Now lets automate, default screen is home_screen automation_object.home_screen.team_link.click #Framework has already executed the waiting hooks in the config above #Now lets print out the team screen title puts automation_object.team_screen.title.textFair Warning:
This is the initial release of this gem, kind of a proof of concept. There is a lot of coupling and very long methods that make this gem less appealing, but it is stable. Although we do use this at our company for all of our UI testing and we have a very stable and scalable testing codebase.
Future Plans:
I plan on creating a new class/object structure, unit testing, internal documentation to support further growth of this gem by the end of Q1 2015. Also considering adding Cucumber step definitions for your use that will implement the AutomationObject framework so that testing will be plug and play, only needing features and configurations from you.
Finally:
I am very grateful that my managers at Spartz allowed me to pursue this idea, even though I had no idea how this would be implemented. The idea ended up working out for us and I hope you may get some use out of it too.
Installation Instructions:
https://github.com/spartzinc/automation_object#installation
Source Code:
https://github.com/spartzinc/automation_object
Examples:
https://github.com/spartzinc/automation_object/blob/master/docs/README.md#examples
RubyGems:
https://rubygems.org/gems/automation_object
- 投稿日:2019-08-22T21:55:39+09:00
『RubyOnRails』enumの使い方
初めに
プログラミングを始めて4ヶ月の初学者です。
今回enumを使う機会があったのでメモを残します。環境
・Ruby '2.3.8'
・Rails '5.2.3'emunとは
enum(イーナム)はRails4.1から導入された機能です。
enumを使用すると以下の様な事が出来ます。
DBの中では数字を保存させる。
Viewでは文字を表示させる。例:日本というテーブルに地方というカラムがあったとします。
enumを使用しない場合は、地方カラムに関東、関東、九州、四国の様に文字が登録されます。
しかし、enumを使用した場合は関東は1、関西は2、四国は3、九州は4と定義する事で、DBの中は1、1、4、3の様に保存され、Viewでは対象の文字を表示させる。emunの利点
・データ型をintegerにするとDBに数字で登録されるが、数字だけだと数字が持つ意味が共有出来ない。
一人で開発する時は自分だけが意味を理解していればいいが、チーム開発だとチーム内で意味が理解できていないといけない。
そこで、enumを使用する事で数字が何を表しているかがチーム内で共有出来る。emunの使用方法(モデル編)
対象にモデルに記述します。
今回はroomというテーブルのcategoryカラムにenumを使用したいと思います。room.rbenum category: { 喜び: 0, 悲しみ: 1, 不思議: 2, 憧れ: 3, 恐怖: 4, 後悔: 5, 期待: 6, 怒り: 7 }これで、数字と文字を関係付ける事ができました。
emunの使用方法(view編)
今回はプルダウン形式で表示させたいと思います。
room.rb<%= form_for(@room) do |f| %> <%= f.select :category, Room.categories.keys.to_a, {} %> <% end %>最後に
分かりにくい記事かもしれませんが、初学者の助けになれば幸いです。
- 投稿日:2019-08-22T21:25:32+09:00
mapメソッドとは?
mapメソッドとは?
mapメソッドは
配列の要素数だけ繰り返し処理を行うメソッドです。mapメソッドの書き方は?
mapメソッドは
配列が入った変数.map{|変数名|処理名}と記述します。処理後は戻り値で配列を生成します。
例を出して説明すると
@brand = Brand.all ##{グッチ、シャネル、サンローラン} @brand.map{|t| [t.name, t.id]} ##[[グッチ、1],[シャネル,2],[サンローラン,3]]といった配列が生成されます。
eachとの違いは?
eachメソッドを使用した場合、返り値はレシーバ自体になります。
一方、mapメソッドで生成された配列はそのまま保持されます。
- 投稿日:2019-08-22T20:10:09+09:00
コミットメッセージにチケット番号+[半スペ]が無い場合エラーを返すスクリプト
業務ルールでRedmineとコミット内容を紐ずけるため、
#00000 コミットメッセージでコミットをするという内部ルールがあります。
ただうっかり入力し忘れたり、半角スペースが全角スペースになってRedmineと紐図かなかったりというまれにあったので、Gitフックを使用して対策をしてみたいと思います。Gitフックとは
Gitフックは、Gitでコマンドを実行する直前もしくは実行後に特定のスクリプトを実行するための仕組み。
commit-msg フック
コミットメッセージを入力後、処理を走らせることができる。
以下格納先。.git/hooks/commit-msg
.sampleを外し、フックスクリプトとして使用する。
他にも、
コミット直前に実行:pre-commit
プッシュ直前に実行:pre-push
など色々とある。Rubyで書く
個人的にRubyを学習中だったのでRubyでスクリプトを記述しました。
1行目に以下を記述。#!/usr/bin/env ruby
#!はシェバングと言い、これ以下に書いてあるコマンドで実行し直してくれる。
/usr/bin/envを使う事でwhich rubyで出てくる環境依存のPATHを記述しなくてもよくなる。
※/usr/bin/envも実は環境依存だがほぼ共通で入っている。。。はず。内容
#!/usr/bin/env ruby # #00000+[半スペ] 、Mergeコミット以外エラー message = File.read(ARGV[0]) $regex = /#\d+\s|^Merge branch/ if !$regex.match(message) puts "\e[31mチケット番号入力してください\e[0m" exit(1) endARGV(アーグヴイ)
コマンドラインからスクリプトの引数として与えられた文字列を要素として持つ。
# ファイルを読み込んだ際コマンドラインの第一引数を実行する File.read(ARGV[0])matchメソッド
正規表現とmatchメソッドを使用し、定義した正義表現に当てはまらない場合はエラーメッセージを実行し処理を中断させる。
exitコマンド
エラーの文字列を表示した後、exitコマンドで処理を終了させる。
exit(0):正常終了
exit(1):以上終了色を変更する
エラーメッセージの色を変えた方が視覚的にわかりやすいのでメッセージの色を変更する為、エスケープシーケンスを使用。
エスケープシーケンスとは
ターミナル上で色を含む特定の制御を実現するための特殊な文字列print "\e[31mhello\e[0m" # 赤色感想
Gitフックをもっと活用すれば、コミット前orプッシュ前にエラーを検知したり色々なことができそう!
一番手こずったのはシェバングでした!!
(最初書き方がわからず全然Rubyを認識しませんでした。。。)
- 投稿日:2019-08-22T19:58:55+09:00
サブクラス一覧を配列にして取得(.subclasses禁止縛り)
やりたいこと
qiita.rbclass LandSuper end class RepublicSub < LandSuper end class MonarchySub < LandSuper end # SuperとかSubはスーパークラス、サブクラスの意味 # この状況で[RepublicSub,MonarchySub]という配列が欲しい縛り
その1:.subclasses禁止
Class.subclassesはActiveSupportというライブラリにしか入っていません。(Ruby on Railsに付属しているらしい)
現在作っているプログラムが既に相当重いので、おそらくここでしか使わない機能のためにライブラリをrequireする案は却下。その2:サブクラスに追記禁止
「仕様変更でサブクラスを増やした時に書き忘れてバグ発生」みたいな未来が見えるので、サブクラス側は一行も実装しません。
RepublicSubとMonarchySubは空クラスで行きます。ダメだった方針……ObjectSpace.each_object
ActiveSupportの中ではObjectSpace.each_objectというメソッドを使っているらしく、
これを実装すればいいという情報がネットには多かったです。
https://www.xmisao.com/2014/02/11/ruby-how-to-get-subclasses.html
http://nomnel.net/blog/ruby-get-subclasses/
しかしObjectSpaceというのが何なのか調べてもよくわからず、コピペして改変してみても(良い子のみんなは真似しないでね)
動かなかったため断念。筆者の結論……inherited (Class)
https://ref.xaio.jp/ruby/classes/class/inherited
自動で動くメソッドと言えば、インスタンスが作成された時に自動で回るinitializeメソッドが有名ですね。
あれの「newされた時」ではなく、「継承された時」バージョンがinheritedメソッドです。
というわけで筆者の結論は、
「まず空の配列をスーパークラスのクラス変数として用意し、継承されるたびにサブクラスを追加する」です。qiita.rbclass LandSuper @@polity=[] def self.inherited(subclass) @@polity.push(subclass) end def self.polity @@polity end end class RepublicSub < LandSuper end class MonarchySub < LandSuper end p LandSuper.polity # => [RepublicSub, MonarchySub]クラスオブジェクトではなく文字列オブジェクトで取得するなら、
配列に入れるsubclassに.nameを付けてください。qiita.rbclass LandSuper @@polity=[] def self.inherited(subclass) @@polity.push(subclass.name) end def self.polity @@polity end end class RepublicSub < LandSuper end class MonarchySub < LandSuper end p LandSuper.polity # => ["RepublicSub", "MonarchySub"]100回継承したら100回、1000回継承したら1000回クラス変数の値が変わるので、
コメントで説明するなり.freezeするメソッドを作って継承し終わったら凍結させるなりした方がいいかもしれません。未検証項目
挙動を確認したのはスーパー、サブ共に自作クラスの場合なので、
「既存クラスをオープンしてinheritedメソッドを使ったらどうなるのか」はわかりません。
また「継承が一段ではなく、孫クラスひ孫クラスまで継承したらどうなるのか」もわかりません。
誰か教えてください。(悪質なコメ稼ぎ)
- 投稿日:2019-08-22T19:55:28+09:00
[rails] 孫要素のカウント数(条件)で子要素の値を返す方法
孫要素の条件で子要素の値を返す
はじめに
孫要素をincludes
Prefecture.includes(localities: :sub_locality)子モデルをキャッシュ&絞込
Prefecture.includes(:localities).references(:localities).where("localities.name = ?", '東京都')子モデル・孫モデルが存在するレコード抽出
Prefecture.joins(:localities).where("localities.name = ?", '新宿区') Prefecture.joins(localities: :sub_localities).where("sub_localities.name = ?", '西新宿')ここまでは、いろいろな記事でもっとわかりやすく書いてるものを参考にしてください。
本題
ここからが本題です!
今回ワタシが苦戦した内容が、「孫要素が必要な条件揃っていたら、子要素の値を返す」というものでした。上記の例をつくるとすると、
1つのprefectureの 紐づくlocalityに、さらに紐づくsub_localityが100以上ある場合のみ値を返すコードを作りたい試行段階
Prefecture.first.localities.joins(:sub_localities).group(:id).having('count_id >= 100').count(:id) => {2=>131, 3=>116, 11=>167, 13=>334, 15=>172, 16=>144, 17=>164, 19=>180, 24=>113, 38=>109, 186=>143}こんな感じの結果が返ってくる。
locality.idをとれたので、成功!?しかし、これで
localityを絞るには、locality_ids = Prefecture.first.localities.joins(:sub_localities).group(:id).having('count_id >= 100').count(:id).keysのようにして、
locality.idをとってきてから、Locality.where(id: locality_ids)と書かないといけない!めんどくさい
結果
一回で絞り込めないかな〜〜と検索してたらドンピシャのサイトがありました。
http://akinov.hatenablog.com/entry/2017/05/13/163911Prefecture.first.localities.joins(:sub_localities).group(:id).having("count('*') >= ?", 100) => #<ActiveRecord::AssociationRelation [#<Locality id: 11, prefecture_id: 1, name: "~~~" ]>としっかり
localityのデータが返ってきました。
having("count('*') >= ?", 100)こんな書き方でいけちゃうみたいです!
'*' ここは名前?みたいな感じなのでなんでも良き。(なはず)Prefecture.first.localities.joins(:sub_localities).group(:id).having("count('*') >= ?", 100).count => {2=>131, 3=>116, 11=>167, 13=>334, 15=>172, 16=>144, 17=>164, 19=>180, 24=>113, 38=>109, 186=>143}ちなみに、count つけるとこんな感じでデータが帰ってきます。
まとめ
- google様での検索ワードってホント大事。
- これが完全正解とは、限らないのでもっといい方法をご存じの方はご教授願います。
- 投稿日:2019-08-22T17:40:46+09:00
rbenvでRubyのバージョンアップを行う
rbenvとは
rbenvとは、複数のRubyのバージョンをOSの中で共存させて、必要に応じてRubyの環境を切り替えられるツールです。自分の環境にrbenvが入っていなかったら、git cloneでGitHubからインストールします。apt ではインストールできないようです。
公式サイト https://github.com/rbenv/rbenv
rbenvのバージョンを上げる
rbenvコマンド自体のバージョンが古いと、最新のRubyがインストールできない事があります。(正確にはruby-buildのバージョンが影響している)その場合は、rbenvコマンド自体のバージョンを上げないといけない事になります。
現状のrbenvのバージョンでインストール可能なRubyのバージョンの一覧が表示されます。一覧の中に、インストールしたいバージョンが含まれていなければ、rbenvコマンドのバージョンを上げる事になります。
rbenv install -lrbenvのバージョンアップの前に、現状のrbenvのバージョンを確認しておきましょう。
rbenv -vrbenvのバージョンを上げるには、先ず、rbenvが入っているディレクトリに移動します。自分の環境(Ubuntu)では、/usr/local/rbenvでした。
cd /usr/local/rbenv
git pull確かに、バージョンが上った事を確認します。
rbenv -vrbenvだけでなく、ruby-buildもバージョンアップしないといけない事になります。
cd /usr/local/rbenv/plugins/ruby-build
git pullこれで、最新のRubyのバージョンが表示される筈です。
rbenb install -l最新のRubyのバージョンをインストールする
現状インストールされているRubyのバージョン一覧を表示します。*がついているバージョンが、現状、有効になっているRubyのバージョンという事になります。systemが表示されれば、OSにプレインストールされていたrubyのバージョンがsystemに該当します。
rbenv versionssystemが実際に何のバージョンであるかを調べたい場合は、適当なディレクトリに移動した後、これで確認できます。
rbenv local system
cat .ruby-version.ruby-versionファイルは、確認のために、一時的に作成しただけなので、確認が終わったら削除しておいて下さい。
rbenv local --unset.ruby-versionが本当に削除された事を確認しておく。一番したに表示されていなければOK。
ls -latr今回は、2.3.0のバージョンのRubyをインストールします。(この間が多少長いので、しばし、休憩
)
rbenv install -v 2.3.0インストールしたRubyが表示される事を確認します。
rbenv versionsグローバル環境で、Rubyのバージョンを変更する
蛇足ではあるが、グローバル環境のバージョンを確認する方法は4つあります。
cat /usr/local/rbenv/version--- たぶん、使わないと思われる
rbenv versions--- 他バージョンも表示してくれるので便利
rbenv version--- グローバル環境1つだけを表示
ruby -v--- ローカル環境を指定していない事が条件ではあるグローバル環境を2.3.0に変更します。バージョンをきっちりと入力しなくても、Tabキーで補完入力ができます。
rbenv global 2.3.0グローバル環境が確かに変更された事を確認します。
rbenv versionsこの時点で自作したRubyのプログラムを流しても、グロバール環境にインストールしたgemを使っている場合、最新バージョンの環境ではgemが未だインストールされていないため、エラーになります。なので、最新バージョンの環境で、グローバル環境に必要なgemを1個つづインストールする必要があります。
元の環境に戻したい場合は、元のバージョンを指定すれば戻ります。p247とかのパッチレベルまでしっかりと指定しないといけません。
rbenv global 2.0.0p247旧バージョンでグローバル環境にインストールしていたgemの一覧を保存しておきます。
gem list > gem_list_2.0.0.txtもう一度、グローバル環境を最新バージョンに変更します。
rbenv global 2.3.0旧バージョンのgemのlistを基に、必要なgemをインストールします。バージョン指定が必要な場合は、指定します。
gem install gem名 -v 0.0.0自作したRubyのプログラムを動かしてみて、動作に問題がなければ、旧バージョンのRubyは削除しておきます。インストールにはあれだけ長い時間がかかった割りには、削除は一瞬だったりする。
rbenv uninstall 2.0.0p247旧バージョンのRubyが削除された事を確認します。
rbenv versionsC'est fini
- 投稿日:2019-08-22T16:41:23+09:00
【Rails】 API開発で『Can't verify CSRF token authenticity』といわれたときの対応
現状の問題
RailsでAPI開発をしている際にエンドポイントを叩いたら以下のようなエラーが出ました。
Can't verify CSRF token authenticity. Completed 422 Unprocessable Entity in 22ms (ActiveRecord: 0.0ms)CSRFトークン認証ができなかったという内容のエラーです。
解決方法
方法1. application_controller.rbを修正
controllers/application_controller.rbを見ると以下のようなコメントがあります。Prevent CSRF attacks by raising an exception.
For APIs, you may want to use :null_session instead.コメントに従い、以下のように変更すれば問題は解決します。
- protect_from_forgery with: :exception + protect_from_forgery with: :null_sessionこの変更により、CSRF対策が『例外の発生』から『セッションのクリア』になります。
『セッションのクリア」の場合、処理は継続されるためAPIのエンドポイントを叩いたら結果が返ってくるようになります。方法2. APIで利用するcontrollerを修正
APIで利用するcontrollerに対して以下のメソッドを追加します。
skip_before_action :verify_authenticity_tokenこちらのほうが、
application_controller.rbを修正するのに比べて影響範囲が限定的になります。
- 投稿日:2019-08-22T15:50:51+09:00
Rails6 Webpackerでエラーが出た
はじめに
Rails6で新しくアプリを作ろうと思ったがハマってしまったので、備忘録を残していきます。
アプリ作成開始
いつも通りrails newをしていきます。
$ rails new hoge_appさてサーバー軌道をさせよう。
$ rails sするとエラー発生。
$ rails s => Booting Puma => Rails 6.0.0 application starting in development => Run `rails server --help` for more startup options RAILS_ENV=development environment is not defined in config/webpacker.yml, falling back to production environment Exiting Traceback (most recent call last): 80: from bin/rails:3:in `<main>' 79: from bin/rails:3:in `load' 78: from /Users/yuichiro/app/task_app/bin/spring:15:in `<top (required)>' 77: from /Users/hoge/.rbenv/versions/2.6.3/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in `require' 76: from /Users/hoge/.rbenv/versions/2.6.3/lib/ruby/2.6.0/rubygems/core_ext/kernel_require.rb:54:in `require' ・ ・ (省略) ・ ・ /Users/yuichiro/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/webpacker-4.0.7/lib/webpacker/configuration.rb:91:in `rescue in load': Webpacker configuration file not found /Users/yuichiro/app/task_app/config/webpacker.yml. Please run rails webpacker:install Error: No such file or directory @ rb_sysopen - /Users/yuichiro/app/task_app/config/webpacker.yml (RuntimeError)下記コマンド実行しろと言われているので実行します。
$ rails webpacker:install Yarn not installed. Please download and install Yarn from https://yarnpkg.com/lang/en/docs/install/yarnがインストールされてないと言われているので、インストールします。
$ brew install yarnyarnもインストールできたので、再度webpackerをインストール
$ rails webpacker:install identical config/webpacker.yml Copying webpack core config exist config/webpack identical config/webpack/development.js identical config/webpack/environment.js identical config/webpack/production.js identical config/webpack/test.js Copying postcss.config.js to app root directory identical postcss.config.js Copying babel.config.js to app root directory identical babel.config.js Copying .browserslistrc to app root directory identical .browserslistrc The JavaScript app source directory already exists apply /Users/yuichiro/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/webpacker-4.0.7/lib/install/binstubs.rb Copying binstubs exist bin identical bin/webpack identical bin/webpack-dev-server append .gitignore Installing all JavaScript dependencies [4.0.7] run yarn add @rails/webpacker from "." yarn add v1.17.3 [1/4] ? Resolving packages... [2/4] ? Fetching packages... [3/4] ? Linking dependencies... warning " > webpack-dev-server@3.8.0" has unmet peer dependency "webpack@^4.0.0". warning "webpack-dev-server > webpack-dev-middleware@3.7.0" has unmet peer dependency "webpack@^4.0.0". [4/4] ? Building fresh packages... success Saved 1 new dependency. info Direct dependencies └─ @rails/webpacker@4.0.7 info All dependencies └─ @rails/webpacker@4.0.7 ✨ Done in 3.92s. Installing dev server for live reloading run yarn add --dev webpack-dev-server from "." yarn add v1.17.3 [1/4] ? Resolving packages... [2/4] ? Fetching packages... [3/4] ? Linking dependencies... warning "webpack-dev-server > webpack-dev-middleware@3.7.0" has unmet peer dependency "webpack@^4.0.0". warning " > webpack-dev-server@3.8.0" has unmet peer dependency "webpack@^4.0.0". [4/4] ? Building fresh packages... success Saved 1 new dependency. info Direct dependencies └─ webpack-dev-server@3.8.0 info All dependencies └─ webpack-dev-server@3.8.0 ✨ Done in 3.25s. Webpacker successfully installed ? ?webpackerがインストール出来たので、もう一度サーバーを起動してみる。
$ rails sまとめ
rails6からWebpackerがデフォルトでインストールされているので、webpackerやyarnをインストールしていない人は僕と同じようにハマるかもしれないので、参考にしてみてください!
- 投稿日:2019-08-22T15:11:35+09:00
NullMailかどうかをチェックする
ActionMailer::MessageDeliveryにラップされてるので、.messageを使うのがポイントです。require 'rails_helper' RSpec.describe MyMailer, type: :mailer do describe '.hoge' do subject { described_class.hoge } context 'when something is wrong' do it 'returns NullMail' do expect(subject.message).to be_a ActionMailer::Base::NullMail end end end end参考
- 投稿日:2019-08-22T14:44:02+09:00
[Rails] Could not load the 'listen' gem. Add `gem 'listen'` to the development group of your Gemfile (LoadError)
$ rails sしようとしたら、
.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/ activesupport-5.1.7/lib/active_support/dependencies.rb:292:in `require': Could not load the 'listen' gem. Add `gem 'listen'` to the development group of your Gemfile (LoadError)と怒られた。
config/environments/development.rb内の
config/environments/development.rbconfig.file_watcher = ActiveSupport::EventedFileUpdateCheckerをコメントアウトしたらいけた。
参考: https://www.oipapio.com/question-890966
config.file_watcher: config.reload_classes_only_on_changeがtrueの場合にファイルシステム上のファイル更新検出に使われるクラスを指定します。デフォルトのRailsではActiveSupport::FileUpdateChecker、およびActiveSupport::EventedFileUpdateChecker(これはlistenに依存します)が指定されます。カスタムクラスはこのActiveSupport::FileUpdateChecker APIに従わなければなりません。
- 投稿日:2019-08-22T13:32:08+09:00
ridgepoleで既存テーブルのデータをコピーしたりTRIGGERを設定したりする
前置き
古くからあるテーブル(
old_posts)を新しいテーブル(new_posts)に切り替える対応をしていて、その過程でレコードを同期するためにridgepoleでいろいろ操作したのでそのメモです。コード
# old_postsにある既存のレコードをすべてnew_postsにコピーする execute(<<-COPY) do |c| INSERT INTO new_posts(title, content, created_at, updated_at) SELECT title, content, created_at, updated_at FROM old_posts; COPY # まだnew_postsにレコードがない場合のみ実行 c.raw_connection.query(<<-SQL).count.zero? SELECT 1 FROM new_posts SQL end # TRIGGERを設定して、old_postsへのレコード追加時にnew_postsにもレコード追加する execute(<<-TRIGGER) do |c| CREATE TRIGGER copy_post AFTER INSERT ON old_posts FOR EACH ROW BEGIN INSERT INTO new_posts(title, content, created_at, updated_at) VALUES (NEW.title, NEW.content, NEW.created_at, NEW.updated_at); END; TRIGGER # まだcopy_post TRIGGERがない場合のみ実行 c.raw_connection.query(<<-SQL).count.zero? SHOW TRIGGERS WHERE `Trigger` = 'copy_post' SQL end今回は扱うテーブルの性質上、レコード更新/削除時は考慮していません。
(必要な場合は別途TRIGGERを追加していけばOK)このあと、モデルのテーブル名を変更するなどの対応を進めていく予定。
いやー、DB系操作するの結構疲れるなぁ。
![]()
以上です。
![]()
参考
- 投稿日:2019-08-22T12:28:49+09:00
Rails6 のちょい足しな新機能を試す68(CurrentAttributes.before_reset 編)
はじめに
Rails 6 に追加されそうな新機能を試す第68段。 今回は、
CurrentAttributes.before_reset編です。
Rails 6 では、CurrentAttributesにbefore_resetコールバックが追加されました。
reset される前に呼ばれます。
また、resetコールバックの別名としてafter_resetが追加されています。Ruby 2.6.3, Rails 6.0.0.rc1 で確認しました。Rails 6.0.0.rc1 は
gem install rails --prereleaseでインストールできます。
(Rails 6.0.0 がリリースされましたが、動作確認した時点での最新は、 Rails 6.0.0.rc1でした。悪しからず)
$ rails --version Rails 6.0.0.rc1ちょっと適切な例を思いつかなかったので、 User Agent の情報をログに出力するために、
before_resetを無理矢理、使ってみます。プロジェクトを作る
rails new rails6_0_0rc1 cd rails6_0_0rc1User の CRUD を作る
User の CRUD を作ります。
bin/rails g scaffold User nameCurrentAttributes の派生クラスを作る
user_agent属性を追加してbefore_resetでログに、 User Agent の情報を出力するようにします。app/models/current.rbclass Current < ActiveSupport::CurrentAttributes attribute :user_agent before_reset { log_user_agent } private def log_user_agent Rails.logger.info("#{Thread.current}: user_agent = #{Current.user_agent}") end endCurrentRequest を作る
ApplicationControllerでインクルードするためのモジュールを作ります。app/controllers/concerns/current_request.rbmodule CurrentRequest extend ActiveSupport::Concern included do before_action do Current.user_agent = request.user_agent end end endApplicationController を修正する
ApplicationControllerでCurrentRequestをインクルードします。app/controllers/application_controller.rbclass ApplicationController < ActionController::Base include CurrentRequest end動作確認する
rails serverを起動してから、ブラウザで http://localhost:3000/users にアクセスしてみます。ログに User Agent の情報が表示されることがわかります。
... #<Thread:0x0000556a86f33bd0@puma 004@/usr/local/bundle/gems/puma-3.12.1/lib/puma/thread_pool.rb:89 run>: user_agent = Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36試したソース
試したソースは以下にあります。
https://github.com/suketa/rails6_0_0rc1/tree/try068_current_attribute_before_reset参考情報
- 投稿日:2019-08-22T11:19:18+09:00
paramsとform_withについて【初学者の備忘録】
paramsとは
・HTTPリクエストで送信されたデータを、一時的に保存するためのメソッド
なのですが、内部の動きはその通りでも、初学者にとっては、コードをパッと見るだけではよくわからないのです。。。
この記事ではあるあるなコードで解説します。viewでの動き
まず、下記のようにform_withで入力データを飛ばすことを考えます。
posts_controller.rbdef new @posts = Post.new endnew.html.erb(posts_controller)<div class="container"> <%= form_with(model: @posts, local: true) do |f| %> <div class="form-group"> <%= f.label :title, "タイトル" %> <%= f.text_field :title, class: "form-control" %> </div> <div class="form-group"> <%= f.label :summary, "要約" %> <%= f.text_area :summary, size: "20x5", class: "form-control" %> </div> <div class="form-group"> <%= f.label :description, "本文" %> <%= f.text_area :description, size: "20x10", class: "form-control" %> </div> <div class="form-group"> <%= f.label :url, "参考URL" %> <%= f.text_area :url, size: "20x1", class: "form-control" %> </div> <%= f.submit "投稿する", class: "btn btn-primary" %> <% end %> </div>理解したいポイント
1. <% form_with(model: @posts... の、model: @postsの部分。
2. <%= f.text_field :title...や、<%= f.text_area :summary...などの入力フォームの属性詳細
1.<% form_with(model: @posts... の、model: @postsの部分。
→form_withでmodelオプションをつけると、
引数のインスタンス(@posts)が何も情報を持っていない場合、createアクションへ、
情報を持っている場合、updateアクションへ自動的に振り分けてくれます。→今回はnewしているので、createアクションへ飛びます。
2.<%= f.text_field :titleの部分
→:titleは、あくまでparamsに保存する際のキーです。
最終的に、DBのtitleカラムに保存するため、:titleとする必要があります。
paramsに保存するだけなら、ここは:user_nameでも:timeでも良いです。:titleとしない場合、ストロングパラメーターの検証を通るが、DBに保存することができません。
(permit(:hoge)は合わせる必要ありですが)
ここら辺が、こんがらがるポイントかと思っています。DBへの保存処理は、次のcreateアクションで実施します。
下記のような。posts_controller.rbdef create @post = current_user.posts.new(post_params) if @post.save! redirect_to @post, notice: "「#{@post.title}」を投稿しました。" else render :new end end private def post_params params.require(:post).permit(:title, :summary, :description, :url) endポイントは、
post_paramsメソッド内の、
params.require(:post).permit(:title, :summary, :description, :url)です。
この:postとか、:titleは、あくまでparamsで受け取った値のキーを指定しているだけです。createメソッドの
@post = current_user.posts.new(post_params)の部分で初めて
paramsからキーと値が渡されます。
paramsのキーとDBカラムが一致しない場合は、ここでエラーが表示されてしまいます。
- 投稿日:2019-08-22T10:56:19+09:00
iQueryの$でis not defined;をはかれた時の対処法
「$」マークでエラーが出た時の対処法。
app/assets/javascripts/ファイル名.js
にjQueryで記述する際の最初に使う「$」マークでエラーが出た時は実は簡単に消せます。
前提として、app/assets/javascripts/application.jsには
//= require jquery //= require jquery.turbolinks //= require jquery_ujs //= require rails-ujs //= require bootstrap //= require activestorage //= require turbolinks //= require_tree .これらが書かれてるものとします。
注意: require_tree.は一番最後の記述にしてください。解決方法
エラー画面にもあるadd /* global $*/を上にそのまま追加することによってエラーは消えます。
他にも解決策があると思いますが自分でこれで解決したので投稿させていただきます。
誰かの助けになれば幸いです。
- 投稿日:2019-08-22T10:49:04+09:00
RubyMineで既存プロジェクトを開いた際の注意点
概要
Run Configuration Error:[No Rails found in SDK]への対応について
RubyMineを初めて使った際にはまったので備忘録として書いておく環境
OS:MacOS Mojave
Ruby:2.6.3
anyenv下のrbenvでインストール現象
RubyMineで既存プロジェクトを開いて「Run Development project」しようとしたところ
下記のエラーが表示されて実行することができませんでした。Run Configuration Error:[No Rails found in SDK]また、ググって下記の対応してみましたが解決しませんでした。
- .ideaディレクトリを削除して再起動
- Tools-Bundler-install
- 「Edit Configurations」にてRuby SDKを「Use project SDK」や「Use other SDK」を変更
どちらでも適正に設定されていれば大丈夫
- 「Edit Configurations」にてBundlerタブの「Run the script〜」にチェックをいれる
これだけでは解消しませんが、しておく必要はあります
原因
- プロジェクト内にインストールされたgemをRubyMineが認識できないこと 下記サイトの記述による気づくことができました Pleiades - RubyMine201902
この場合、Bundlerはgemsを vendor/bundle ディレクトリーにインストールし、.bundle/config ファイルをプロジェクトのルートに追加します。RubyMineはこの設定ファイルを処理して、gemsが vendor/bundleにインストールされていることを検出します。
また、~/.bundle/configで「BUNDLE_PATH: "vendor/bundle"」を設定していると
Tools-Bundler-installでオプションなし実行するだけでは、
プロジェクトのディレクトリ内にconfigファイルを生成しないことも原因でした。対策
Tools-Bundler-installする際にオプションに下記を指定する
--path vendor/bundle
そうすればプロジェクト内に.bundle/configが設定されてエラーは解消されます
その他
RubyMineでインストールするとvendor/bundle下の階層がcmdでインストールした場合と違うが、configに記載されるのは
vendor/bundleで同じRubyMine:vendor/bundle/ruby/バージョン/gems cmd:vendor/bundle/gemsこれは、それぞれを下記で実行していたためということがわかりました
RubyMine:rbenv exec bundle install --path vendor/bundle cmd:bundle install --path vendor/bundle
- 投稿日:2019-08-22T08:10:33+09:00
[編集途中]railsでtwitter認証する
twitter developerの設定は省く
コンソール$ rails _5.1.6_ new twitter-authGemfilesource 'https://rubygems.org' gem 'rails', '5.1.6' gem 'puma', '3.9.1' gem 'sass-rails', '5.0.6' gem 'uglifier', '3.2.0' gem 'coffee-rails', '4.2.2' gem 'jquery-rails', '4.3.1' gem 'turbolinks', '5.0.1' gem 'jbuilder', '2.7.0' gem 'omniauth' gem 'omniauth-twitter' gem 'dotenv-rails' #環境変数を簡単に利用できるgem group :development, :test do gem 'sqlite3', '1.3.13' gem 'byebug', '9.0.6', platform: :mri end group :development do gem 'web-console', '3.5.1' gem 'listen', '3.1.5' gem 'spring', '2.0.2' gem 'spring-watcher-listen', '2.0.1' end group :test do gem 'rails-controller-testing', '1.0.2' gem 'minitest', '5.10.3' gem 'minitest-reporters', '1.1.14' gem 'guard', '2.13.0' gem 'guard-minitest', '2.4.4' end group :production do gem 'pg', '0.20.0' end # Windows環境ではtzinfo-dataというgemを含める必要があります gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]コンソール$ bundle update $ bundle install $ rails generate controller Users home $ touch .env $ touch config/initializers/omniauth.rb.envTWITTER_CONSUMER_KEY = '**************' TWITTER_CONSUMER_SECRET = '**************'config/secrets.ymldefault_twitter: &default_twitter twitter_api_key: <%= ENV["TWITTER_CONSUMER_KEY"] %> twitter_api_secret: <%= ENV["TWITTER_CONSUMER_SECRET"] %> development: secret_key_base: //事前に数値が入っている <<: *default_twitter test: secret_key_base: //事前に数値が入っている <<: *default_twitter production: secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> twitter_api_key: <%= ENV["TWITTER_CONSUMER_KEY"] %> twitter_api_secret: <%= ENV["TWITTER_CONSUMER_SECRET"] %>以下を追加
gitignore/.envconfig/initializers/omniauth.rbRails.application.config.middleware.use OmniAuth::Builder do provider :twitter, ENV['TWITTER_CONSUMER_KEY'], ENV['TWITTER_CONSUMER_SECRET'] endコンソール$ rails g model user provider:string uid:string username:string image_url:string $ rails db:migrate $ rails db:migrate RAILS_ENV=testapp/models/user.rbclass User < ApplicationRecord def self.find_or_create_from_auth_hash(auth_hash) provider = auth_hash[:provider] #providerはどのサービスで認証したのかを見分けるもの uid = auth_hash[:uid] name = auth_hash[:info][:name] image_url = auth_hash[:info][:image] #find_or_create_by()は()の中の条件のものが見つければ取得し、なければ新しく作成するというメソッド self.find_or_create_by(provider: provider,uid: uid) do |user| user.username = name user.image_url = image_url end end endapp/controllers/users_controller.rbclass UsersController < ApplicationController def home end def create user = User.find_or_create_from_auth_hash(request.env['omniauth.auth'])#request.env['omniauth.auth']はTwitter認証で得た情報を格納するもの if user session[:user_id] = user.id session[:user_name] = user.username redirect_to root_path, notice: "ログインしました。" else redirect_to root_path, notice: "失敗しました。" end end endconfig/routes.rbRails.application.routes.draw do get 'users/home' get 'auth/:provider/callback' => 'users#create'#このpathを通して認証が行われる。 root 'users#home' endapp/views/users/home.html.erb<h1>Users#home</h1> <p>Find me in app/views/users/home.html.erb</p> <%= link_to 'Twitterでログイン', '/auth/twitter' %> <%= session[:user_name] %>コンソールrails s参照
- 投稿日:2019-08-22T00:50:41+09:00
RubyOnRails/Ethereumとの連携
プログラミングスクールの課題で個人アプリの作成という課題がある。
個人的にはすごく重きを置いているカリキュラムなんだけれども、とにかく自分の作りたいものを作るというコンセプトで作成をしていくつもり。
で、僕の作りたいものとしてどうしてもスマートコントラクトの機能を使いたい。
スクールの課題ということもあるので、スマートコントラクトを実装したRailsのwebアプリケーションを作るという方針で行こうと思ってます。
ネット上を調べたところ、railsでイーサリアムに接続してコントラクトコードを実行するという手法があることがわかったので、簡単にまとめようかなと思います。
動作環境
・Rails v5.2.3
・ethereum.rb v2.2
・Ganache v2.1.0
rails newでプロジェクト作成
いつも通りですね。プロジェクトを作ります。
rails new ethereum-testgemのthereum.rbをインストール
このgemが今回の肝とも言えるかもしれません。
イーサリアムサーバーに接続し、コントラクトコードの実行を可能にするgemです。
Gemfileにethreum.rbを記述してbundle installします。
// Gemfileに記載 gem 'ethereum.rb' // ターミナルで実行 bundle installコントラクトコードの実装
プロジェクトのルートパス配下にcontractsフォルダを作成し、コントラクトファイルを作成して実装します。
ethereumのコントラクトを実装するには、solidityという言語を使用します。
コードの説明は別日に基礎からブログにまとめていこうかと思うのですが、ごく簡単な処理を記述しています。
機能としては、デプロイ時に渡した文字列を呼び出したり、デプロイしたオーナーのアドレス/残高を取得できるだけのものになっています。
contracts/HelloWorld.sol
pragma solidity ^0.4.24; contract HelloWorld { string public greeting; address public owner; function HelloWorld(string _greeting) { greeting = _greeting; owner = msg.sender; } function greet() constant public returns (string) { return greeting; } function getBalance() constant public returns (uint balance) { return owner.balance; } function getAddress() constant public returns (address) { return owner; } }コントラクトコードの実装
コントラクトコードを記述したので、TopControllerというコントローラーファイルを作成します。
ここの記述でethereum.rbを利用したEthereumへの接続を実施を行います。
app/controllers/top_controller.rb
class TopController < ApplicationController ETHEREUM_TOKEN_PATH = "#{Dir.pwd}/contracts/HelloWorld.sol" GANACHE_URL = 'HTTP://127.0.0.1:7545' def index @client = Ethereum::HttpClient.new(GANACHE_URL) #① @contract = Ethereum::Contract.create(file: ETHEREUM_TOKEN_PATH, client: @client) #② @contract.deploy_and_wait('Hello, World!') #③ end end①ではGanacheに接続するための@clientオブジェクトを作成します。GANACHE_URLにはGanacheアプリケーションのRPC SEVERに表示されているURLを入力します。
②ではcreateメソッドを使ってcontractインスタンスを生成しています。
③で作成したコントラクトをブロックチェーン上にデプロイします。
ちなみにviewではこんな記述にしています。
app/views/top/index.html.erb
<! -- index.html.erb --> <div class="container"> <h3>Ethereum.rb テストページ</h3> <p>アドレス: <%= @contract.call.get_address() %></p> <p>残高: <%= @contract.call.get_balance()%></p> <p>GreetMethod: <%= @contract.call.greet() %></p> </div>@contract.call.get_address()これだけで、HelloWorld.solに記述したfunctionを呼び出すことができます。
Ganacheの起動
アプリと連携させるためにGanacheを起動させます。
Ganacheはイーサリアム開発用のパーソナルブロックチェーンです。
起動するだけでアカウント・残高・契約作成・ガスコストなどを確認できるので、ブロックチェーン関連のアプリケーションを作成した場合に、テストとして有用です。
ブラウザで動作確認
アプリを起動させて、http://localhost:3000/にアクセスします。
bundle exec rails sこんな感じのサイトにアクセスできればOKです。
うーん、たったこれだけではあるんだけど、概念理解にすごく時間がかかってしまった。
ほんとはsolidityを使ったコントラクトコードとフロントエンドの連携は、web3.jsっていうjavascriptのフレームワークを使ったりするらしいんですが・・。
個人アプリではそこまで新機能もりもりにするのはちょっとつらいので、ethereum.rbを使って連携をして、Railsコントローラの感覚に落とし込んでからコントラクトコードをビューで反映する、という手法で行こうかなと思っています。
- 投稿日:2019-08-22T00:44:55+09:00
Homebrew のインストール方法とエラー対策について
macOSのパッケージ管理システムである、Homebrewのインストール方法について、備忘録も兼ねて投稿します。
※エラーの対処方法については、後半で触れています。インストール方法
ターミナルを起動し、以下のコマンドを入力します。
※コマンドはHomebrewの公式サイトからコピペ可能ターミナル$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" (省略) Press RETURN to continue or any other key to abort ==> Password: (省略)途中の「Press RETURN〜」でEnterを押し、password:でOSのパスワードを入力すればOKです。
※パスワードは入力しても文字が表示されないので、きちんと入力されているのか不安になりますが、そのまま入力しEnterを押せば大丈夫です。以上で、Homebrewのインストールは完了です。
最後に、正しくインストールされているか、以下のコマンドで確認します。ターミナル$ brew doctor Your system is ready to brew.このように、「Your system is ready to brew.」と表示されたら、無事にインストールが完了しています。
なお、自分の場合は以下のようなエラーが発生したため、対処方法についても記しておきます。
エラー内容
ターミナルWarning: "config" scripts exist outside your system or Homebrew directories. `./configure` scripts often look for *-config scripts to determine if software packages are installed, and which additional flags to use when compiling and linking. Having additional scripts in your path can confuse software installed via Homebrew if the config script overrides a system or Homebrew-provided script of the same name. We found the following "config" scripts: /Users/name/.pyenv/shims/python3.6m-config /Users/name/.pyenv/shims/python-config /Users/name/.pyenv/shims/python3-config /Users/name/.pyenv/shims/python3.6-configこれは、PATH環境変数にpyenvのディレクトリが含まれてしまっていることが原因で、エラーが起こっています。そのため、以下のコマンドを入力することで、Homebrewを実行するときにPATH環境変数にpyenvのディレクトリを含まないようにすることできます。
ターミナル$ alias brew="PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin brew"再度「$ brew doctor」を実行して、「Your system is ready to brew.」が表示されればOKです。
参考にさせていただいたサイト
- 投稿日:2019-08-22T00:44:55+09:00
Homebrew のインストール方法について(エラーの対処方法についても触れています。)
macOSのパッケージマネージャーである、Homebrewのインストール方法について、備忘録も兼ねて初投稿です。
※エラーの対処方法については、後半で触れています。インストール方法
ターミナルを起動し、以下のコマンドを入力
※コマンドはHomebrewの公式サイトからコピペ可能ターミナル$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" (省略) Press RETURN to continue or any other key to abort ==> Password: (省略)途中の「Press RETURN〜」でEnterを押し、password:でOSのパスワードを入力すればOKです。
※パスワードは入力しても文字が表示されませんが、そのまま入力してEnterを押せば大丈夫です。以上で、Homebrewのインストールは完了です。
最後に、正しくインストールされているか、以下のコマンドで確認します。ターミナル$ brew doctor Your system is ready to brew.このように、「Your system is ready to brew.」と表示されたら、無事にインストールが完了しています。
なお、自分の場合は以下のようなWaningが発生したため、対処方法についても記しておきます。
エラー内容
ターミナルWarning: "config" scripts exist outside your system or Homebrew directories. `./configure` scripts often look for *-config scripts to determine if software packages are installed, and which additional flags to use when compiling and linking. Having additional scripts in your path can confuse software installed via Homebrew if the config script overrides a system or Homebrew-provided script of the same name. We found the following "config" scripts: /Users/name/.pyenv/shims/python3.6m-config /Users/name/.pyenv/shims/python-config /Users/name/.pyenv/shims/python3-config /Users/name/.pyenv/shims/python3.6-configこれは、PATH環境変数にpyenvのディレクトリが含まれてしまっているため、以下のコマンドを入力することで、Homebrewを実行するときにPATH環境変数にpyenvのディレクトリを含まないようにすることできます。
ターミナル$ alias brew="PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin brew"再度「$ brew doctor」を実行して、「Your system is ready to brew.」が表示されればOKです。
参考サイト









