20190405のRailsに関する記事は18件です。

世界初? "アイテムで繋がるSNS" を作ってみた。 ~顔やステータスよりも,持ち物で勝負する~

"アイテムで繋がるSNS"を初心者が2ヶ月で作って見ました

個人間で互いにレンタルができる匿名CtoCサービス(無料)があったら面白そうだと思い作りました。将来、企業への広告媒体としてのモデル(下ネタ以外でも)の可能性があるのかなと。作ってきた経緯等を此方の記事に書きたいと思います。ありそうでなかった?(無知でしたらすいません↓

個人的に"SSS(ソーシャル-シェアリング-システム)"と名付けました。
Ruby on Railsで作り、後ろでどんな技術が使ったのか簡単に解説します。
そして、少しエロいです(笑)

  • メッセージ機能
    メッセージ機能

  • ユーザー・検索機能

スクリーンショット 2019-04-03 21.20.37.png

  • Add-Item 機能

スクリーンショット 2019-04-03 21.28.44.png

  • 武器を買う
    商品購入ページ or ECサイトへ

...等をGoogle先生を調べながら実装しました。

URL
Den-app 

スペック

  • 使用言語等など

    • Ruby 2.5.1
    • Rails 5.2.1
    • Vagrant CentOS7
  • 著者プロフィール

    • プログラミング歴 約1年
      (去年の 5月13日〜14日位から)
    • Rubyのチェリー本 => Rails チュートリアル => クローンアプリ制作後,実際に自分の考えたアプリを作ろうと思い, "Den-app"を制作しました。
    • PG,転職探し中
    • 祝 初サイト:sunny:

- メッセージ機能(リアルタイム). ~ Action Cable ~

  • ここからは実際に使用した技術を2種類紹介いたします。
    どちらも, Rails5.2系で標準なので詳しい素晴らしい記事は他に多くあります。
  • "den-app"にどのような効果をもたらしたかを書きたいと思います。

1つ目は、個人間でのメッセージ機能をページ推移なしで行えるように,"ActionCable"を使用しました。これを使えば、非同期でサーバーと通信が出来ます。

messaging.gif

ActionCableは日本語のページ等も多く、技術自体は簡単に実装できたのですが、理想の挙動にするのが私の力不足で時間が掛かり、1ヶ月程掛かりました。
QItaは勿論の事、意外と英語用のプログラミング質問サイト等にサラッと金言が載ってたりして血眼で探した記憶があります。

こういう非同期で通信することを"Ajax化"と呼ぶそうで、ActionCableではないですがden-appではもう一箇所この技術を利用している箇所があります。

  • 借りたい申請

items.gif

皆さんの持ち物に"借りたい”という申請をするページですが、"Ajax化"で、更新せずとも Create & Destroyアクションを送信できます。素晴らしいですね:eyes:

- 画像アップロード. ~ Active storoge ~

Railsで画像アップロードと聞くと、現在でもやはり,CarrierWaveが人気のようです。探して見ても圧倒的に情報が載って居ました。
Den-appではrails標準の最近追加された,"Active storoge" とストレージにAWSのS3を用いています。採用理由としては、

  • 新しい技術好き
  • gem追加が要らない
  • 最近の紹介ページが意外と多い(2018年頃~)
  • 名前が格好良い(笑)

からです。Modelに

user.rb
class User < ApplicationRecord
  has_one_attached :image
  ....
end

とてもシンプルで使いやすいです。
S3との相性?も良いらしく、バケットを追加後アップデート出来るようになりました。CarrierWaveを使っている人も一度使って見ては如何でしょうか?
画像リサイズやデフォルトイメージ(初期画像)も調べればできます。

  • プロフィール編集機能

edit.gif

- Add-Item 機能で"Active Stroge"は使用されています。クローンアプリを練習した時、CarrierWaveを使用したのですが、現代の段階では標準装備がActive Storageよりも多く便利です。私としても使い分けて使用していきたいと思います。

本番へのデプロイ

Railsから繋げる本番環境としてはHerokuを使用しています。Pushコマンド1つで更新できるのはとても魅力がありますね。

ただ、現在直面している問題がネイキッドドメイン(www無し)からDen-app(www有り)へのリダイレクトが出来ない。。。Railsの機能として,

config/production.rb
Rails.application.configure do
  ...
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
  config.force_ssl = true
  ....
end

でSSHへのリダイレクトや,○○○..herokuapp.comから独自ドメインへのリダイレクトは設定できたが、ネイキッドドメインからのアクセスが未だに出来ない↓
今後とも勉強していきます。優しい人、教えて下さい。

総括

纏めて見ましたが、一言で言うと,"Ruby on Railsは凄まじい"に尽きます。
私のような初心者でも、完璧ではなくともアイデアをサービスとして開発できました。

今後とも、Den-appの研磨は勿論のこと、色々作りたいサービスがあるので影でひっそりと一人で作っていきたいと思います。都内で週末などに、一緒にプログラミングをできる方がいればな〜と思っています。(気軽にコメントやTwitterのDM等で連絡くれると嬉しいです。)

Den-appに少しでも興味を持った方は是非登録して見て下さいね。
詳しい使い方は"HowToUse"に載っています。素敵な事があるかもしれません。

記事を読んで頂き、大変感謝いたします。
Den-app 

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

世界初? 一人でひっそりと "アイテムで繋がるSNS" を作ってみた。 ~顔やステータスよりも,持ち物で勝負する~

"アイテムで繋がるSNS"を初心者が2ヶ月で作って見ました

個人間で互いにレンタルができる匿名CtoCサービス(無料)があったら面白そうだと思い作りました。将来、企業への広告媒体としてのモデル(下ネタ以外でも)の可能性があるのかなと。作ってきた経緯等を此方の記事に書きたいと思います。ありそうでなかった?(無知でしたらすいません↓

個人的に"SSS(ソーシャル-シェアリング-システム)"と名付けました。
Ruby on Railsで作り、後ろでどんな技術が使ったのか簡単に解説します。
そして、少しエロいです(笑)

  • メッセージ機能
    メッセージ機能

  • ユーザー・検索機能

スクリーンショット 2019-04-03 21.20.37.png

  • Add-Item 機能

スクリーンショット 2019-04-03 21.28.44.png

  • 武器を買う
    商品購入ページ or ECサイトへ

...等をGoogle先生を調べながら実装しました。

URL
Den-app 

スペック

  • 使用言語等など

    • Ruby 2.5.1
    • Rails 5.2.1
    • Vagrant CentOS7
  • 著者プロフィール

    • プログラミング歴 約1年
      (去年の 5月13日〜14日位から)
    • Rubyのチェリー本 => Rails チュートリアル => クローンアプリ制作後,実際に自分の考えたアプリを作ろうと思い, "Den-app"を制作しました。
    • PG,転職探し中
    • 祝 初サイト:sunny:

- メッセージ機能(リアルタイム). ~ Action Cable ~

  • ここからは実際に使用した技術を2種類紹介いたします。
    どちらも, Rails5.2系で標準なので詳しい素晴らしい記事は他に多くあります。
  • "den-app"にどのような効果をもたらしたかを書きたいと思います。

1つ目は、個人間でのメッセージ機能をページ推移なしで行えるように,"ActionCable"を使用しました。これを使えば、非同期でサーバーと通信が出来ます。

messaging.gif

ActionCableは日本語のページ等も多く、技術自体は簡単に実装できたのですが、理想の挙動にするのが私の力不足で時間が掛かり、1ヶ月程掛かりました。
QItaは勿論の事、意外と英語用のプログラミング質問サイト等にサラッと金言が載ってたりして血眼で探した記憶があります。

こういう非同期で通信することを"Ajax化"と呼ぶそうで、ActionCableではないですがden-appではもう一箇所この技術を利用している箇所があります。

  • 借りたい申請

items.gif

皆さんの持ち物に"借りたい”という申請をするページですが、"Ajax化"で、更新せずとも Create & Destroyアクションを送信できます。素晴らしいですね:eyes:

- 画像アップロード. ~ Active storoge ~

Railsで画像アップロードと聞くと、現在でもやはり,CarrierWaveが人気のようです。探して見ても圧倒的に情報が載って居ました。
Den-appではrails標準の最近追加された,"Active storoge" とストレージにAWSのS3を用いています。採用理由としては、

  • 新しい技術好き
  • gem追加が要らない
  • 最近の紹介ページが意外と多い(2018年頃~)
  • 名前が格好良い(笑)

からです。Modelに

user.rb
class User < ApplicationRecord
  has_one_attached :image
  ....
end

とてもシンプルで使いやすいです。
S3との相性?も良いらしく、バケットを追加後アップデート出来るようになりました。CarrierWaveを使っている人も一度使って見ては如何でしょうか?
画像リサイズやデフォルトイメージ(初期画像)も調べればできます。

  • プロフィール編集機能

edit.gif

- Add-Item 機能で"Active Stroge"は使用されています。クローンアプリを練習した時、CarrierWaveを使用したのですが、現代の段階では標準装備がActive Storageよりも多く便利です。私としても使い分けて使用していきたいと思います。

本番へのデプロイ

Railsから繋げる本番環境としてはHerokuを使用しています。Pushコマンド1つで更新できるのはとても魅力がありますね。

ただ、現在直面している問題がネイキッドドメイン(www無し)からDen-app(www有り)へのリダイレクトが出来ない。。。Railsの機能として,

config/production.rb
Rails.application.configure do
  ...
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
  config.force_ssl = true
  ....
end

でSSHへのリダイレクトや,○○○..herokuapp.comから独自ドメインへのリダイレクトは設定できたが、ネイキッドドメインからのアクセスが未だに出来ない↓
今後とも勉強していきます。優しい人、教えて下さい。

総括

纏めて見ましたが、一言で言うと,"Ruby on Railsは凄まじい"に尽きます。
私のような初心者でも、完璧ではなくともアイデアをサービスとして開発できました。

今後とも、Den-appの研磨は勿論のこと、色々作りたいサービスがあるので影でひっそりと一人で作っていきたいと思います。都内で週末などに、一緒にプログラミングをできる方がいればな〜と思っています。(気軽にコメントやTwitterのDM等で連絡くれると嬉しいです。)

Den-appに少しでも興味を持った方は是非登録して見て下さいね。
詳しい使い方は"HowToUse"に載っています。素敵な事があるかもしれません。

記事を読んで頂き、大変感謝いたします。
Den-app 

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

【Rails on Docker】CSSフレームワークをBootstrapからMaterializeに移行した

Introduction

CSSフレームワークといえばBootstrapということで利用していたのですが、MaterializeというのがBootstrapライクにマテリアルUIが実装できるとあって気になっていまして、S-BRSTでリリース後に切り替えてみました。

Bootstrapをアンインストールして、Materializeをインストールするだけなのですが手こずったので手順をまとめておきます。

Materialize使いやすい!きれい!

前提

Gemfile
gem 'bootstrap', '~> 4.3.1'
gem 'jquery-rails'
app/assets/stylesheets/application.scss
@import "bootstrap";
app/assets/javascripts/application.js
//= require jquery3
//= require popper
//= require bootstrap

1. Bootstrapをアンインストール

GitHub - twbs/bootstrap-rubygem: Bootstrap 4 rubygem for Rails / Sprockets / Hanami / etcにそって設定した項目のうちMaterializeに不要な設定をきれいにします。jQueryは使いたいから残す。

Gemfile
gem 'jquery-rails'
app/assets/stylesheets/application.scss
app/assets/javascripts/application.js
  //= require jquery3

2. Materializeをインストール

MaterializeのインストールはGitHub - mkhairi/materialize-sass: Materializecss rubygem for Rails Asset Pipeline / Sprocketsを利用させていただきました。

Gemfile
gem 'materialize-sass', '~> 1.0.0'
gem 'jquery-rails'
app/assets/stylesheets/application.scss
@import "materialize";
@import "https://fonts.googleapis.com/icons?family=Material+Icons";
app/assets/javascripts/application.js
//= require jquery3
//= require materialize

あとはGemfile.lockにBootstrapの情報が残ったままになってしまっているので一度からファイルにしてgemのインストールをし直します。

$ rm Gemfile.lock
$ touch Gemfile.lock
$ docker-compose build

以上でBootstrapからMaterializeへの移行完了です!

3. 【応用】Bootstrapのpadding/margin使いやすいですよね。

padding, marginの設定の簡単さはBootstrapの魅力でした。
Bootstrapでなくてもあの機能を使うために、mixinを自作します。(Bootstrapのソースを参考に)

app/assets/stylesheets/_spaces.scss
@each $prop, $prop_sub in (margin: m, padding: p) {
  @for $size from 0 through 5 {
    $rem: $size * 0.5;
    @each $direct, $direct_sub in (top: t, bottom: b, left: l, right: r) {
      .#{$prop_sub}#{$direct_sub}-#{$size} {
        #{$prop}-#{$direct}: #{$rem}rem!important;
      }
    }
    .#{$prop_sub}x-#{$size} {
      #{$prop}-right: #{$rem}rem!important;
      #{$prop}-left: #{$rem}rem!important;
    }
    .#{$prop_sub}y-#{$size} {
      #{$prop}-top: #{$rem}rem!important;
      #{$prop}-bottom: #{$rem}rem!important;
    }
    .#{$prop_sub}-#{$size} {
      #{$prop}: #{$rem}rem!important;
    }
  }

  @each $direct, $direct_sub in (top: t, bottom: b, left: l, right: r) {
    .#{$prop_sub}#{$direct_sub}-auto {
      #{$prop}-#{$direct}: auto!important;
    }
    .#{$prop_sub}x-auto {
      #{$prop}-left: auto!important;
      #{$prop}-right: auto!important;
    }
    .#{$prop_sub}y-auto {
      #{$prop}-top: auto;
      #{$prop}-bottom: auto;
    }
    .#{$prop_sub}-auto {
      #{$prop}-top: auto!important;
      #{$prop}-bottom: auto!important;
      #{$prop}-left: auto!important;
      #{$prop}-right: auto!important;
    }
  }
}
app/assets/stylesheets/application.scss
@import 'spaces';

これでMaterializeでもあの便利なpadding/margin設定が利用可能に!

Trouble Shooting

1. Bootstrapをuninstallするとアクセスできなくなる

コンテナは起動しているのに、アクセスできない...
docker-compose.ymlのrailsアプリ用のコンテナの起動コマンドを

docker-compose.yml
command: rails s

から

docker-compose.yml
command: bundle exec rails s -p 3000 -b '0.0.0.0'

に変更したところ解決!詳しくは...わからない...

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

Sidekiqのソース読んでみたメモ

sidekiqのソースを読んでみた

  • sidekiqを使ってるけどなかってどうなってるの?というのを調べることがあったのでまとめ

前提

  • バージョン
    • v5.2.5
  • 読んでみたタイミング
    • 2019/03
  • ここで書かないこと
    • siekiqの使い方
    • Thread周り
  • 基本的なとこだけ読んでます
  • 読んでみたなので正確ではないこともあります。。

クライアント側(jobを積むほう)

Sidekiq::Worker

  • 実行する処理とかを用意するクラスにincludeするモジュール
  • includeしたクラスにperform_asyncとかが特異メソッドとして追加される

#perform_async

  • 中でSidekiq::Clientのオブジェクトを生成してpushを読んでる

Sidekiq::Client

  • redisにjobをつむところの役割をやってる

#push

  • workerに渡す引数+jobのidを用意して整形してatomic_pushに投げる

#atomic_push

  • redisのqueuesていうキーにつむjobのキュー名を入れている(タイプがsetなので同じものを入れるときは重複しない)
  • redisのqueue:キュー名のキーにjobを追加する

サーバー側

  • jobを実行するほう

登場するクラス

  • Sidekiq::CLI
    • サーバー側の起動を行う
    • そのあとは停止などのコマンドを受け付ける
  • Sidekiq::Launcher
    • このオブジェクトのrunを呼べばサーバー側が動く
    • jobを取ってきて処理するのと、retryやスケジュールからqueueを積む処理を起動してくれるのでランチャー
  • Sidekiq::Manager
    • Sidekiq::Processorを作成&ぐるぐる実行させる
  • Sidekiq::Processor
    • 一定時間ごとにqueueをチェックしに行って処理を実行
    • こいつがperformを呼び出してる
  • Scheduled::Poller
    • 即時実行じゃないjobや一度失敗したjpbを確認して、実行タイミングになったらqueueに積む

sidekiq起動のところ

bin/sidekiq

  • Sidekiq::CLI.instance
    • Sidekiq::CLIのインスタンスを生成(instanceってなんだ?と思ったけどシングルトンだった。。)
  • Sidekiq::CLI#parse
    • 設定とかをsetしてる
  • Sidekiq::CLI#run
    • Sidekiq::Launcherのインスタンスを生成&Sidekiq::Launcher#runを呼び出したあとはコマンドを受け付けるためぐるぐるし続ける。
    • Sidekiq::Launcher#run
    • Sidekiq::Manager#startとSidekiq::Scheduled::Poller#startを呼び出す
      • Sidekiq::Manager#start
      • Sidekiq::Processor#startを呼び出す
        • Sidekiq::Processor#start
        • スレッドでrunを実行
          • Sidekiq::Processor#run
          • jobがあればとってきて該当workerのperformを実行をぐるぐる。
      • Sidekiq::Scheduled::Poller#start
      • redisのretryとscheduleの中で実行タイミングになったものを取り出してqueueにつむ。
        • retryとscheduleはzsetで、timestampをキーにしてて、今の時間よりも小さいものーでとってるっぽい

ざっくりかくと
Sidekiq::CLI -> Sidekiq::Launcherを叩いてあとは入力待ちぐるぐる
Sidekiq::Launcher#run -> Sidekiq::Manager#startとSidekiq::Scheduled::Poller#startを叩く
Sidekiq::Manager#start -> Sidekiq::Processorをぐるぐるさせる
Sidekiq::Scheduled::Poller -> ぐるぐる

おまけでRedisに登録されるもの

※ namespaceは省く

キー type
schedule zset 予定されたジョブが入っている
queues set 一度でもジョブが積まれたキューのリスト
stat:processed string 完了したジョブの数
stat:processed:yyyy-mm-dd string 該当日に完了したジョブの数
stat:failed string 失敗したジョブの数
stat:failed:yyyy-mm-dd string 該当日に失敗したジョブの数
queue:キュー名 list そのキューの待機状態のジョブのリスト
limit:processes set TODO (limit:heartbeatのUUIDが入っていた。。)
limit: heartbeat:UUID string TODO (trueとか入ってる。。)
host:port:xxxx:workers hash そのworkerが現在実行中のジョブの情報

感想

  • ランチャーってなんぞと思ったけど、一括で必要なのを起動してくれるもののことらしいと今回知った。。
  • Threadとか詳しくないのでいつかちゃんと触って理解しよう。。
  • redisの型とか全然知らなかったのでちょっと知れてよかった。
  • gemを読んでみたって記事はありなのか。。?(お勉強メモなのでお許しください。。)
  • 顔文字とか絵文字のメソッドがちょいちょいあって面白かった
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[PG::UndefinedTable: ERROR: relation "XXXXXX" does not exist] への対応

問題

heroku run rails db:migrateを行うと、こんなエラーがでた

PG::UndefinedTable: ERROR:  relation "param_types" does not exist
: CREATE TABLE "param_values" ("id" bigserial primary key, "name" character varying, "presentation" character varying, "param_type_id" bigint, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL, CONSTRAINT "fk_rails_e74ade1df5"
FOREIGN KEY ("param_type_id")
  REFERENCES "param_types" ("id")
)

ParamValueというテーブルを作ろうとしたら、
その中でParamTypeというテーブルのid(=param_types.id)が参照されている。

しかしParamTypeというテーブルは存在しない(=UndefinedTable)ので、
ParamValueより先に作ってください、ということ。

ローカルでmigrationできても、どうやらherokuでは
migration fileは日付順にmigrateされるらしい。

対処

ParamValueよりも先にParamTypeが作られるよう、
手動でmigration fileの日付を変更し
ローカルで正常にmigrateされるのを確認したあと、
herokuにpushした。

手順

  1. rails db:drop
    →この時点でmigration fileの日付を変更してよい
  2. rails db:create
  3. rails db:migrate
  4. 問題なければherokuにpush
  5. heroku pg:reset DATABASE
  6. heroku run rails db:create



おわり

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

SQLite3::ReadOnlyException: attempt to write a readonly databaseへの対応

rails db:dropを実行したときにエラーがでたため(なんのエラーか忘れた)、
sudo rails db:dropをしてDB削除成功。

その後sudo rails db:createでDBを作成し、
rails db:migrateを行ったところ、下記エラーが発生。

WARNING: Nokogiri was built against LibXML version 2.9.8, but has dynamically loaded 2.9.4
rails aborted!
ActiveRecord::StatementInvalid: SQLite3::ReadOnlyException: attempt to write a readonly database: CREATE TABLE "schema_migrations" ("version" varchar NOT NULL PRIMARY KEY)

ReadOnlyExceptionだって。

権限の問題かと思い調べたら、chownで権限を変更すればよいとの情報が。


けどsudo rails db:createしたのがいけなかったのでは?と思い、
再度DBを削除しsudo抜きのrails db:createおよび
rails db:migrateを実行したところ、うまくmigrateされました。


おわり

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

プログラミング学習記録48〜あとは条件分岐だけ〜

今日やったこと

  • ユーザー退会機能を実装するために奮闘する

今日も昨日の続きで、ユーザー退会機能を実装するためにいろいろやってみました。

いろいろやった結果、退会ボタンを押した時に退会できるアクションを作ることができました。

ただ、そのユーザーの投稿状況やいいね!してる投稿によってはうまく退会できないことが判明したので、条件分岐をうまく使って退会機能を作れないかなと思ってます。

具体的に説明すると、、、

  • Postテーブルに退会したいユーザーの投稿が残っているかどうか
  • 他の人がいいね!した自分の投稿があるかどうか

という感じです。

ユーザー全員がユーザーの投稿が残っていて、他の人がいいね!した自分の投稿がある場合は条件分岐せずに退会機能をつけることができます。

ただ、必ずしもみんなが

  • 何かしらを投稿して、
  • 他の人に自分の投稿がいいね!されている

状態で退会するわけではないので、今のままだとかなり限定された人しか退会できなくなってしまいます。

今のままだと自分の投稿がなくて、他の人からのいいね!もない時に「メソッドが定義されてないですよ〜」というRailsおなじみの煽りを受けることになります。

正直、解決方法がわからないのでteratailで聞いてみました。

回答が返ってこないようであれば、MentaなどでRailsの得意な方に聞いてみたいと思います。

あとちょっとで完成!というところで足止めを食らっていますが、なんとか完成させたいです。

明日からも引き続きプログラミング学習頑張ります。

おわり

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

【Rails/JavaScript】Googleマップ上にある同じ座標の複数マーカーをずらす

個人開発のWebアプリまちかどルートv5.62への実装メモです。

Googleマップのマーカーが重なる

まちかどルートでは位置情報付きの投稿をすべて「ルートマップ」と名付けたGoogleマップ上にマーカー表示させています。

ちなみにgmaps4railsgeocoderというgemを使っています。

使い方についてはこちらの記事などを参考にしました。

しかしながらまったく同じ座標の投稿があると複数のマーカーが重なってしまい、とても不便です。

maxRandomDistanceを使う

handler = Gmaps.build('Google', { markers: { maxRandomDistance: 5 } });

viewに使うhandler = Gmaps.build('Google');の部分を上記のようなコードに変更すると、同じ座標にある複数のマーカーを下の写真のようにずらして表示できるようになります。

ランダムにずれるので細かな調整には不向きですが、簡単な対応策として良いのではないでしょうか。

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

Railsで「CarrierWave+fog」を使ってAWSのS3へアップロード

はじめに

Railsアプリを外部サービスと連携させてみようと思い、AWSが提供するS3へ画像や動画をアップロードしてみた過程をまとめていきます。
今回はCarrierWaveで単純にアップロード機能を利用し、fogでクラウド上のs3へ簡易的にアップロードできるようにしています。

AWS上での設定

S3の詳しい利用法の要点をまとめます。

①AWSアカウントの取得
 AWSのアカウントを取得。原則としてクレジットカードの登録が必要になります。アカウント作成から12か月間は無料枠(最大5GB)としてS3が利用できます。

②IAMユーザーの作成
 続いてIAMユーザーを作成します。IAMとはAWS上のサービスを操作するユーザーと、ユーザーアクセス権限を管理するものです。
IAMがなかった場合、フルアクセスのAWSアカウントをみんなで共有することになります。
ユーザーがアクセスするための認証情報(アクセスキー、ポリシーの設定)を取得しS3へアクセスします。

※ここで取得したアクセスキーIDとシークレットアクセスキーは絶対に控える&定期的に更新する

③バケットの作成
 バケットとは、ファイルなどのオブジェクトを格納するための入れ物です。ここでバケット名を決めるのですが、注意が必要です。AWSバケット名の命名規則に従った名前を付けてください。https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/dev/BucketRestrictions.html
自分の場合、バケット名に不適切な文字を記述してしまい、原因がわからずS3にいつまでたってもアクセスできない事態に見舞われました。

続いてバケットのリージョンを設定します。リージョンとはS3のサービスが提供されている場所を意味します。「アジア・パシフィック(東京)」の場合、使用する資格情報は「ap-northeast-1」となります。

CarrierWaveの導入

gem 'carrierwave'
gem 'fog'

アップロードファイルの作成
$ rails g uploader file
app/uploaders/file_uploader.rbが生成されます。

file_uploader.rb
class FileUploader < CarrierWave::Base
  require 'streamio-ffmpeg'

  if Rails.env.production?
    storage :fog
  else
    storage :file 
  end

  def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end

  def extension_white_list
    %w(jpg jpeg gif mp4 MOV wmv)
  end

  version :screenshot do
    process :screenshot
    def full_filename (for_file = model.logo.file)
      "screenshot.jpg"
    end
  end

  def screenshot
    tmpfile = File.join(File.dirname(current_path), "tmpfile")

    File.rename(current_path, tmpfile)

    movie = FFMPEG::Movie.new(tmpfile)
    movie.screenshot(current_path + ".jpg", { resolution: '500x600' },preserve_aspect_ratio: :width)
    File.rename(current_path + ".jpg", current_path)

    File.delete(tmpfile)
  end
end

サムネイル用にffmpegを使用しています。
今回はアップロードされたファイルが画像でも動画でも、一旦tmpフォルダーにjpgファイルとして格納し、最終保存先を開発環境時はローカルに、本番環境時はfogに設定しています。

続いてcarrierwave.rbを作成します。

carrierwave.rb
require 'carrierwave/storeage/fog'

CarrierWave.configure do |config|

  config.fog_provider = 'fog/aws'

  config.fog_credentials = {
    provider: 'AWS',
    aws_access_key_id: 'アクセスキー',
    aws_secret_access_key: 'シークレットアクセスキー',
    region: 'リージョン',
  }

  config.fog_directory = 'バケット名'
  #日本語ファイル名の設定
  CarrierWave::SanitizedFile.sanitize_regexp = /[^[:word:]\.\-\+]/
  config.cache_dir = "#{Rails.root}/tmp/uploads"
end

モデルにuploaderを紐づけます。

gallery.rb
class Gallery < ApplicationRecord
  mount_uploader :file, FileUploader

viewの実装は今回は割愛します。
これで本番環境時にS3にアップロードすることができました。

おわり

特に基盤となってくるuploaderとcarrierwaveの設定はまだ完全に理解していないし、不十分なところもあると思うので今後さらに深堀していきたいです。

参考

https://qiita.com/junara/items/1899f23c091bcee3b058
http://vdeep.net/rubyonrails-carrierwave-s3
https://qiita.com/yukiyukimiyaiwa/items/a9e0103c8342b81f6ac1
https://stackoverflow.com/questions/15717368/uploading-image-to-s3-using-carrierwave-and-fogs-bad-uri

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

RailsでStripeのPlan(定期購入商品)の情報を取得する

前提

stripegem を使う。

gem 'stripe'

方法

Stripe::Plan.all でPlan(定期購入商品)の一覧を取得できる。

Stripe::Plan.all
=> #<Stripe::ListObject:0x3fefc6771f14> JSON: {
  "object": "list",
  "data": [
    {"id":"plan_Epxxxxxxxxxxxx","object":"plan","active":true,"aggregate_usage":null,"amount":480,"billing_scheme":"per_unit","created":1554439001,"currency":"jpy","interval":"month","interval_count":1,"livemode":false,"metadata":{},"nickname":"product_name","product":"prod_Epxxxxxxxxxxxx","tiers":null,"tiers_mode":null,"transform_usage":null,"trial_period_days":60,"usage_type":"licensed"}
  ],
  "has_more": false,
  "url": "/v1/plans"
}

classはArrayとなっている。

Stripe::Plan.all.data.class
=> Array
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ruby on RailsでStripeのPlan(定期購入商品)の情報を取得する

前提

stripegem を使う。

gem 'stripe'

方法

Stripe::Plan.all でPlan(定期購入商品)の一覧を取得できる。

Stripe::Plan.all
=> #<Stripe::ListObject:0x3fefc6771f14> JSON: {
  "object": "list",
  "data": [
    {"id":"plan_Epxxxxxxxxxxxx","object":"plan","active":true,"aggregate_usage":null,"amount":480,"billing_scheme":"per_unit","created":1554439001,"currency":"jpy","interval":"month","interval_count":1,"livemode":false,"metadata":{},"nickname":"product_name","product":"prod_Epxxxxxxxxxxxx","tiers":null,"tiers_mode":null,"transform_usage":null,"trial_period_days":60,"usage_type":"licensed"}
  ],
  "has_more": false,
  "url": "/v1/plans"
}

classはArrayとなっている。

Stripe::Plan.all.data.class
=> Array
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ruby on RailsでStripeのPlanの情報を取得する

前提

stripegem を使う。

gem 'stripe'

方法

Stripe::Plan.all でPlanの一覧を取得できる。

Stripe::Plan.all
=> #<Stripe::ListObject:0x3fefc6771f14> JSON: {
  "object": "list",
  "data": [
    {"id":"plan_Epxxxxxxxxxxxx","object":"plan","active":true,"aggregate_usage":null,"amount":480,"billing_scheme":"per_unit","created":1554439001,"currency":"jpy","interval":"month","interval_count":1,"livemode":false,"metadata":{},"nickname":"product_name","product":"prod_Epxxxxxxxxxxxx","tiers":null,"tiers_mode":null,"transform_usage":null,"trial_period_days":60,"usage_type":"licensed"}
  ],
  "has_more": false,
  "url": "/v1/plans"
}

classはArrayとなっている。

Stripe::Plan.all.data.class
=> Array
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ActiveRecord::StatementInvalid: PG::UndefinedTable: ERROR: relation "#{table_name}" does not exist

事象

こんなエラーが出てきた

     ActiveRecord::StatementInvalid:
       PG::UndefinedTable: ERROR:  relation "#{table_name}" does not exist
       LINE 8:                WHERE a.attrelid = '"#{table_name}"'::...
                                                 ^
       :               SELECT a.attname, format_type(a.atttypid, a.atttypmod),
                            pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod,
                            c.collname, col_description(a.attrelid, a.attnum) AS comment
                       FROM pg_attribute a
                       LEFT JOIN pg_attrdef d ON a.attrelid = d.adrelid AND a.attnum = d.adnum
                       LEFT JOIN pg_type t ON a.atttypid = t.oid
                       LEFT JOIN pg_collation c ON a.attcollation = c.oid AND a.attcollation <> t.typcollation
                      WHERE a.attrelid = '"#{table_name}"'::regclass
                        AND a.attnum > 0 AND NOT a.attisdropped
                      ORDER BY a.attnum

解決方法

migrationファイルが消えているので作り直す

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

[JavaScript]ajax通信の重複を回避する方法

ajax通信の重複を回避するには

ajax()によって非同期通信をする時、イベントが発生するたびに同じ値を取得する方法を説明していきます。
まず下記のコードを見てください

ajax.js
$('html要素').on('keyup', function(){
        var input = $(this).val();

        $.ajax({
            type: 'GET',
        url: url,
        data: { keyword: input },
        dataType: 'json'
        })
        .done(function(data) {
          //処理
        })
        .fail(function() {
        //処理
        });


このようにキーが押されるたびにajax通信によって処理が行われるコードがあります。
ただしこの場合押されるたびに通信してしますので取得するデータが同じデータの場合重複して取得することになります。

それを防ぐのがjqxhrオブジェクトです。
これはajax通信をする前にjqxhrオブジェクトを判定しオブジェクトが存在する場合はajax通信を実行しません。
これによりデータの取得の重複を伏せづことができます。

ajax.js
var jqxhr; //追記部分
$('html要素').on('keyup', function(){
        var input = $(this).val(); 
        if (jqxhr){        //追記部分
            return;
        }

        jqxhr = $.ajax({  //追記部分
            type: 'GET',
            url: url,
            data: { keyword: input },
            dataType: 'json'
        })
        .done(function(data) {
          //処理
        })
        .fail(function() {
        //処理
        });


このように記述することによりキーを押した時jqxhrオブジェクトの判定が行われ、オブジェクトがあれば実行しません。

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

Rspec beforeブロックの使い方

• before(:each)
describe または context ブロック内の 各テストの前に実行される。
before(:example), before も同じ意味になる。もしブロック内に4つのテストがあれば、before のコードも4回実行される。

テストごとに実行され、他のテストの状況を受けづらいので基本はこれを使う。

• before(:all)
describe または context ブロック内の 全テストの前に一回だけ実行される。before(:context) も同じ意味になる。before のコードは一回だけ実行され、それから4つのテストが実行される。

• before(:suite) はテストスイート全体の全ファイルを実行する前に実行される。

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

Rails: CSVファイルを使った初期データの流し込み

初期データ流し込み用コード

db/seeds.rb
require 'csv'

csv_data = CSV.read('db/questions.csv', headers: true)
csv_data.each do |data|
  Question.create!(period_id: data[0], content: data[1])
end

解説していきます。

前提

データベース構造は以下のようになっています。

スクリーンショット 2019-04-05 7.32.49.png

periodsテーブルとquestionsテーブルが1対多の関係ですね。

準備

CSVファイルを作成します。
今回はquestionsテーブルのperiod_idcontentカラムを対応させます。

スクリーンショット 2019-04-05 7.46.59.png

ファイルの準備が出来たら以下のようにdbディレクトリ直下に配置します。

スクリーンショット 2019-04-05 7.49.40.png

いよいよ初期データを流し込んでいきます。

流し込み

csvファイルの読み込みとデータを流し込むコードは以下のように書けます。
(header 有りの場合)

db/seeds.rb
require 'csv'

csv_data = CSV.read('db/csvファイル名', headers: true)
csv_data.each do |data|
  モデル名.create!(カラム名: data[0], カラム名: data[1])
end

今回の場合は以下のようになります。

db/seeds.rb
csv_data = CSV.read('db/questions.csv', headers: true)
csv_data.each do |data|
  Question.create!(period_id: data[0], content: data[1])
end

今回はquestionsに紐付くperiodsも固定されているのため一緒に作成しました。
最終的には以下のようなコードになります。

db/seeds.rb
require 'csv'

periods = ["introduction", "幼少期", "小学校", "中学校", "高校", "大学", "社会人", "未来", "現在", "conclusion"]

periods.each do |period|
  Period.create!(name: period)
end

csv_data = CSV.read('db/questions.csv', headers: true)
csv_data.each do |data|
  Question.create!(period_id: data[0], content: data[1])
end

コマンド一発で流し込みです。
$ rails db:seed

確認

$ rails c

> Question.all

スクリーンショット 2019-04-05 8.16.42.png

ちょっと分かり難いですが、上手くいきました。

テーブル表示

toppages_controller.rb
def index
    @questions = Question.all
end
index.html.erb
<table class="table table-striped table-bordered">
  <% @questions.each do |question| %>
  <tr>
    <td align="center"><%= question.period.name %></td>
    <td align="center"><%= question.id %></td>
    <td><%= question.content %></td>
  </tr>
  <% end %>
</table>

スクリーンショット 2019-04-05 8.24.17.png

完成!!

参考

csvファイルを作成し、初期データを挿入しよう[Rails]

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

Herokuに画像を投稿する方法

【前提】
・localでの画像投稿の設定はできてる
・画像投稿は gem carrierwave を使用しての投稿

AWS S3を使う

Railsでの開発をしていてHerokuにアップしたところ、git上に入っている画像は表示されていた(背景画像とかロゴ画像とか)がサービス利用の中で画像を投稿したときの表示ができていなかったので調べたところAWS S3というサービスを使うらしい。
AWSは今まで使ったことがなかったが意外と簡単に設定ができた。

アカウント登録

こちらから登録できます。
以下の記事をよんでAWSってこわ、、、っていうイメージがあったので私を含む初学者の方の取り扱いには気をつけてください、、、(私もこうなりかけた)
登録から1年間は利用無料らしいです。
初心者がAWSでミスって不正利用されて$6,000請求、泣きそうになったお話。 - Qiita

やることリスト

アカウント登録後に作るものとしては
AWS関連
 - IAMグループ、ユーザー登録(ここでCSVファイルダウンロード←Macで普通に開けなくてもエディタで開けます)
 - S3バケットの作成
Rails関連
 - gemインストール("fog-aws")
 - config/initializers/carrierwave.rb作成&設定記述
 - uploadersフォルダのファイルに画像の格納場所記述

AWS関連の設定はこちらの記事を読み進めて行けば確実にできます!
【Rails】S3へ『CarrierWave+fog』を使って画像アップロードする方法
【Rails5】AWS S3+CarrierWave+Fog::AWSを利用して画像アップロード機能を作成する

Railsでの設定

gemインストール

Gemfile.
gem 'fog-aws' 
$ bundle install

作成&設定記述(keyはべた書き禁止!!!!!)

config/initializers/carrierwave.rb
require 'carrierwave/storage/abstract'
require 'carrierwave/storage/file'
require 'carrierwave/storage/fog'

if Rails.env.production?
  CarrierWave.configure do |config|
    config.fog_provider = 'fog/aws'
    config.fog_credentials = {
      provider: 'AWS',
      aws_access_key_id: 'IAM登録で取得したアクセスキー',
      aws_secret_access_key: 'IAM登録で取得したシークレットアクセスキー',
      region: 'ap-northeast-1'  # S3バケット作成時に指定したリージョン。左記は東京を指す
    }
    config.fog_directory  = 's3-rails-image-uploader' # 作成したS3バケット名
  end
  # 日本語ファイル名の設定
  CarrierWave::SanitizedFile.sanitize_regexp = /[^[:word:]\.\-\+]/ 
end
uploaders/image_uploader.rb
  #fogに画像格納
  if Rails.env.production?
    storage :fog
  else
    storage :file
  end

簡単!!!?

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

RailsでDBに絵文字を保存したい

特に設定しなければ絵文字を書いて保存しようとすると、Incorrect string valueのエラーが発生します。

絵文字を保存する場合は、config/database.ymlのencodingをutfmb4にします。

default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password:
  socket: /tmp/mysql.sock

また、テーブルを作る際もCHARSET=utfmb4を設定します。

create_table "test_table", options: "CHARSET=utf8mb4" do |t|
    t.string "name", null: false
  end

すでに、DBを作っている場合は一度DBをdropして、DBから作り直す必要があります。

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