20190305のRailsに関する記事は28件です。

Railsでページ遷移後にJavaScriptが実行されない問題の解消法

こんにちは、とくめいチャットサービス「ネコチャ」運営者のアカネヤ(@ToshioAkaneya)です。

Railsでページ遷移後にJavaScriptが実行されない問題について解説します。

Railsでページ遷移後にJavaScriptが実行されない問題の解消法

以下の行を削除します。

application.js
//= require turbolinks

turbolinksは初心者にとっては余計な悩みを増やすだけですので、削除するのが良いでしょう。

はてなブックマーク・Pocketはこちらから

はてなブックマークに追加
Pocketに追加

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

「Railsは終わった」と言われる理由

はじめに

Rubyは死んだ、Railsは時代遅れという人が最近増えてきたように思えます。
私自身RubyやRailsを書いて3年位経ちますが、「終わりつつあるな」と実感することが多いです。
そう思った経緯を記事に書いていきます。

Railsの特徴

Railsの特徴というか、流行した要因としては以下の5つが大きいと私は思っています。

  1. テンプレート、パーシャル、レイアウトをERBを使ってすばやく構築できる
  2. Active Recordによってデータベースを簡単に定義、操作ができる
  3. アセットパイプラインによってcss、jsを管理することができる
  4. チュートリアルが充実している
  5. Rubyという柔軟性の高い言語によって開発することができる

私はRailsはこの5本の柱によって支えられていると思っています。
これらの5本の柱のメリットにより、Railsは大流行しました。
すばやく簡単にプロダクトを作ることができ、チュートリアルが充実しているため、新人教育も簡単でした。

しかし時代の流れとともにこのメリットは以下のようにほぼ失われてしまいました。

  1. テンプレート、パーシャル、レイアウトをERBを使ってすばやく構築できる ReactやVue.jsによる保守性の高いフロントエンドが構築できるようになり使われなくなった
  2. Active Recordによってデータベースを簡単に定義、操作ができる これは今でも現役で使える!
  3. アセットパイプラインによってcss、jsを管理することができる webpackerなどによって置き換えられた
  4. チュートリアルが充実している 扱っている内容が段々と古くなってきており、時代に合わなくなりつつある
  5. Rubyという柔軟性の高い言語によって開発することができる 柔軟性が高いゆえに保守が大変。

今現在5本の柱のうち4本はすでに形骸化しつつあります。Railsを使うメリットはほぼActiveRecordの利便性のみです。

過去に比べてRailsの利便性が失われてしまった、だから「Railsは死んだ」と言われているのだと私は思ってます。

これらに要素について順番に解説していきます。

1. テンプレート、パーシャル、レイアウトをERBを使ってすばやく構築できる

RailsではErbをつかって以下のように書くことができます。

<% provide(:title, "ログイン") %>
<h1>Log in</h1>

<div class="row">
  <div class="col-md-6 col-md-offset-3">
    <%= form_for(:session, url: login_path) do |f| %>

      <%= f.label :email %>
      <%= f.email_field :email, class: 'form-control' %>

      <%= f.label :password %>
      <%= f.password_field :password, class: 'form-control' %>

      <%= f.submit "ログイン", class: "btn btn-primary" %>
    <% end %>

    <p>New user? <%= link_to "Sign up now!", signup_path %></p>
  </div>
</div>

しかし大規模になればなるほど、以下のような辛いことが待っています。

  1. jQueryなどでViewの状態を管理するので見通しが悪くなる
  2. cssの管理が大変になる。BEMなどのアプローチで頑張ってもいずれ辛くなる。
  3. パーシャルはレンダリングのみで状態を保持したり、隠蔽することができないため、使いづらい。
  4. form_for、form_withなどのRails独自の記法の挙動が意外と難しい
  5. View側にモデルを持つことができないため、helperやdecoratorなどの関数に依存してしまい、さらに保守が難しくなる。

上記のような課題点によってRails単体ではフロントエンドで負債が積み重なることが多いので、最近ではReactやVue.jsをつかうのが一般的です。
下記はReact一例ですが、コンポーネント化により、状態やcssの影響範囲をクラス範囲内だけに留めることができます。

login.html.erb
<% provide(:title, "ログイン") %>

<%= javascript_pack_tag 'login', 'data-turbolinks-track': 'reload' %>
<%= stylesheet_pack_tag 'login', 'data-turbolinks-track': 'reload' %>

<div id="login"></div>
login.tsx
document.addEventListener('DOMContentLoaded', () => {
  const node = document.getElementById('login');
  ReactDOM.render(<LoginPage />, node);
});
index.tsx
export default class LoginPage extends React.Component<Props, State> {

  constructor(props) {
    super(props);
  }

  private onSubmit = event => {
    event.preventDefault();
    const formData = new FormData(event.target);
    // ログイン処理
  };

  render() {
    return (
      <div className={styles.container}>
        <form method="POST" className={styles.content} onSubmit={this.onSubmit}>
          <div className={styles.title}>
            ログイン
          </div>
          <InputTextField label="メールアドレス" name="email" inputType="email" />
          <InputTextField label="パスワード" name="password" inputType="password" />
          <button className={styles.button} type="submit">
            ログイン
          </button>
        </form>
      </div>
    );
  }
}

Reactなどのフロントエンドのフレームワークを導入することにより以下のようなメリットが得られました。

  1. コンポーネント化によって定数や状態を隠蔽することができ、保守性の高いフロントエンドが構築できる
  2. cssの影響範囲を任意のクラス内に留めることができる。
  3. (TypeScriptを使った場合)型によって安全にプログラミングすることができる。
  4. フロントエンドでネイティブアプリのようにモデル層、通信層などレイヤーを決めて開発できるようになった。

Railsのerbやhelperを殆ど使わずに書くことが一般的な今、ViewにおけるRailsの優位性はなくなりつつあります。
Railsあるあるですが、インスタンス変数地獄、ERBでモデルやクエリを呼び出したりなど、行儀の悪いコーディングも防ぐことができるというだけでもメリットです。

2. Active Recordによってデータベースを簡単に定義、操作ができる

RailsのDB周りは未だに優秀だと感じています。

  • データベースをORMにより簡単に操作が行える
  • マイグレーションによってデータベース定義をバージョン管理できる
  • バリデーションを簡単に定義できる
  • リレーションが簡単に定義できる

欠点を上げるとするならば

  • 難しい処理の場合実際に発行されるクエリがわかりにくい
  • ActiveRecordから逸脱したことをやろうとすると面倒

というぐらいで、普通に使うのであれば、非常に使いやすいです。

他言語のマイグレーションツールとしてはFlywayなどがありますが、
Railsのほうが圧倒的に使いやすいです。

しかし、Railsのようにマイグレーション周りだけ記述できるridgepoleというものがあり、それだけを使うという選択肢もあります。

3.アセットパイプラインによってcss、jsを管理することができる

cssやjsを連結したり圧縮してくれる仕組みです。
これによって複数ファイルでcss、jsを管理したり、出し分けたりするなどのことが簡単に行えました。

ですがこちらもReactやVueを使う場合殆ど使わない機能になります。

それに加えて、Rails向けのフロントエンド用のライブラリの保守が行われなくなってきているのもあり、
フロントエンドのコードをRailsで管理すること自体が難しくなってきています。

4.チュートリアルが充実している

Railsを一通り学ぶことができる良い教材だと思います。

しかし、ReactやVueによるフロントエンド構築が一般的になりつつある今に、
form_withやimage_tagなどのRails独自のマークアップを覚えることはメリットではなくなりつつあります。
とくにform_for、form_tag、form_withは挙動を完全に把握するにはかなりの学習コストが必要です。しかし学んだところでRails以外のフレームワークでは全く必要のない知識ですし、erbによるHtml記述は斜陽なのでこの部分はReactなどjsxを使った方法で学ぶほうが良いのかなと思います。

TDDやデータベースの設計手法などは未だに参考になると思います。

数年前はRailsチュートリアルをやれば誰でも一線級のエンジニアになれる!という感じでしたが、
今では一部の知識は役に立つが、その他の知識はあまり役に立たなくなってきています。

5. Rubyという柔軟性の高い言語によって開発することができる

Railsの記事なのにRubyに言及するのは許してください。

Rubyは確かに良い言語でした。純粋なオブジェクト指向言語で、書きやすい言語だと思っています。

Ruby2系はチームの幸福度を最大化できなかった - Qiita

過去にこのような記事を書きましたが、Rubyは以下のような弱点があり、コードに問題のあるRailsプロダクトが多く生まれてしまいました。

  1. 読みにくい
  2. Rubyしか触っていないエンジニアはある一定レベルで成長が止まる
  3. 美しく書くという文化でしか質を担保する仕組みが無い
  4. Rubyの将来性

1. 読みにくい

Rubyのコードは引数や返り値の定義がないため、実際に読んでみないと何が帰ってくるのかわからないです。
なのでコードリーディングに時間がかかりますし、バグの混入確率も高いです。

そのためにRailsは「設定より規約」を取り入れて、このようにしたら、このように返ってくるというルールみたいなものを決めています。
このような規約は非常にありがたい半面、Railsはこう書いたら動くみたいな覚えゲーとなってしまった感がします。(その覚えたこともRailsでしか役に立たない)

2. Rubyしか触っていないエンジニアはある一定レベルで成長が止まる

これは社内外のエンジニアでRubyしか触ったことがないエンジニアを見て思った感想に近く、具体的に検証していませんが、述べさせていただきます。
Rubyは型やクラスを意識することなく記述することができてしまいます。
そのため、なんとなくな設計指針やなんとなくなクラス設計というのができてしまいますし、業務でも多く見てきました。
(よくあるケースとしてなんとなく、クラスメソッドにしたり、なんとなくインスタンス生成したりなど)

逆にJava、KotlinやGoなどの型定義を行うプログラミング言語の経験があるエンジニアが書くこRubyのコードは比較的美しいです。
Rubyという言語は型を全く定義しなくても動きますが、型を意識して書かなければ簡単に崩壊してしまいます
しかし、型を意識する書き方というのはRubyでは学ぶことはできません。(一応学べるかもしれませんが、Rubyの型は他言語に比べて挙動の把握が難しいです)
このパラドックスにより、質の悪いRailsプロジェクトが生まれやすくなっています。
そのためRubyしか触っていないエンジニアは一定のレベルで成長が止まると考えています。

その他、クラスの継承、インターフェース、ビルダーパターン、リアクティブプログラミング、ジェネリクス、ラムダなどのパラダイムはRubyでは学ぶことはできません。

私自身Rubyを触ったあとにJava,Kotlinを触ったことによりRubyに対する見方が変わったという経験があります。

3.美しく書くという文化でしか質を担保する仕組みが無い

Rubyは他人が書いたコードを読むのにエネルギーが要る言語だと思います。
型定義がある言語では入力と出力の形式がある程度定まっているので、比較的読みやすいです。
Rubyは返り値がどのような型になるかわからないので、メソッド名が妥当であるか?であったり、美しくわかりやすく書かれているかもしくは、テストを書いているか?が重要になってきます。

熟練者のコードは非常に読みやすいかもしれませんが、そうでない場合、コードリーディングが大変です。
こうしたコールドリーディングを簡単にするために、美しく書く文化やテストを書くという文化があるのですが、
どこまで美しく書くか、どの程度テストを書くかは属人的であるので、質が担保しにくいです。
追い打ちをかけるようにRubyは様々な書き方ができてしまうので、よりコードリーディングが難しくなります。
ダメなプログラミング言語の代名詞としてPHPが挙げられますが、それがRubyに置き換わる時が来るかもしれません

TypeScript、KotlinやGoなどのように、型宣言があり、最低限の書き方が担保されている方が読みやすいのではないかと私は思います。
上記のようにRubyは簡単にかけるが、チーム開発をするには上級者向けの言語なので、Rubyによる開発が辛くなってくるのは必然だと思います。

4. Rubyの将来性

これは個人的な愚痴に近いのですが、Rubyの開発の方向性と現場で必要なものがだんだんと違ってきているのではないかと最近は感じています。

Ruby3では速く動作することが頻繁に取り上げられますが、実際にそれでいまエンジニアが抱えている問題が解決するのか・・・?と思ってしまいます。

Rubyでチーム開発しやすいように、型宣言などの開発者を支援するような機能もほしいなという声もあるのではないでしょうか。

そういった背景もあり、型推論言語であったり、並列処理が速い言語などにフォーカスがあたってきているのだと思います。

今後のRailsとRuby界隈

終わったといっているだけでは生産性がないので、自分なりのアイデアや予想も記述しておきます。

Railsの将来性について

全盛期に比べて価値はかなり落ちてしまったように感じますが、

  • 優秀なマイグレーションツール
  • 扱いやすいORM

によって、APIサーバーとしてはまだまだ活用されるのではないかと思います。

バックエンドはRailsで書いて、フロントエンドはReactもしくはVueなどのフレームワークを用いて設計というのがRailsの今後の道かもしれません。

Railsを使うのであれば、以下のような構成が主流になるのではないかと思います。

  • Rails
  • Fast JSON API
  • Webpack
  • React
  • TypeScript
  • 一部の処理をGoなどでマイクロサービス化

とはいえ、Railsが管理しているのはAPIサーバーとデータベースのみなので、このためだけにRailsが選択されるかというとちょっと微妙な気もします。

Rails代替のフレームワーク、言語について

Go

Goへの乗り換えが最近HOTですが、個人的にはGoはきついのではないかなと思います。
Goroutineなど並列処理は優秀ですが、それ以外のことは苦手だと思っています。
理由としては

  • オブジェクト指向的な設計がやりにくい
  • C言語チックなのでポインタなど意識しなければならないことが多い
  • Rubyなどの他言語に比べて不親切

マイグレーション、データベース、APIをすべてGoで実装しようとする人をたまに見かけますが、それって本当にGoでやるべきなのか?と思います。

なので、私の予想としてはRailsプロジェクトが数年後100%Goのプロジェクトに置き換わることはないかなと思います。
バッチ処理などの重い処理がGoに置き換わっていくというのが現実的かなと思います。

Kotlin

筆者としてはKotlinはかなりありなのかなと思っています

  • Null安全、型推論のモダンな言語
  • Ktor(けいとーる)がKotlin/Nativeに対応した
  • Kotlin/JSによってフロントエンドも書くことができる

Kotlinの世界観として、すべてのプラットフォームをKotlinで書けるという物を目指しているので、
実現した暁には、フロントエンド、バックエンド、アプリをすべてKotlinで書くことができます。

しかし、期待値は高いですが、Railsに代替するほどの決め手はまだなくこれからって感じだと思います。

Node.js

私はあまり触ったことがないのでわからないですが、フロントエンドでTypeScript、JavaScriptを書くので、
サーバーサイドもJSのほうが学習コストが少なくて済むかもしれないので流行るかもしれません。

また、フロントエンドとバックエンドの一部モデルの共通化などNode.jsでできるかもしれません。

その他

Elixirなどありますが、私は触ったことがないのでよくわからないです。

Rubyの型システム予想

ここは完全に妄想なので、興味ない人は飛ばしてください。

メソッド

Ruby3系以降では以下のような感じになってほしいなと思います。

  def add(x : Integer, y : Integer) : Integer
    x + y
  end

Integer以外が入ったときには静的解析などで通知してくれると嬉しいです。
Typescriptのように複数の型を返すときは以下のようにかけるといいと思いました。
ただ、Trueクラス、Falseクラスが存在する中でBooleanクラスをすんなり導入できるかどうかで意見が分かれそうです。

  def method(x : Integer, y : Integer) : Integer | nil
    if x > y
      x
    else
      nil
    end
  end

Ruby3の開発状況は全然知らないのですが、
Rubyに型の秩序を取り入れるという選択肢をユーザーに与えてみてもいいのではないかと思います。

クラス

抽象クラスやメソッドのスコープがわかりやすく定義できると良いなと思いました。

Rubyの場合オブジェクト指向的なプログラミングへのサポートが弱いです。
継承を行うだけで見通しの悪いコードになってしまいがちなので、言語的にサポートがほしいです。

abstract class ApplicationRecord < ActiveRecord::Base

  open def method(x : Integer) : Boolean
    x > 10
  end

  private def save
    #.....
  end
end

class User < ApplicationRecord

  override def method(x : Integer) : Boolean
    x > 20
  end

end

おわりに

数年前はRails学べばなんでもできると言われていましたが、今ではちょっとつらいかなと言う印象です。
主にフロントエンドでは、ネイティブアプリのようにAPIだけ問い合わせてレンダリング、状態管理、キャッシュするというプロダクトが主流になりつつあります。

さらにRubyはチーム開発にはあまり向いていない言語だと思うので、コードレビューや設計方針にあまりエネルギーを割くことがないプログラミング言語が人気になると思います。

という感じでRailsは終わっていないかもしれないが、積極的に学んでも、Railsの特徴の殆どはこれから活躍する見込みが無いので、あまり得られるものはない。と思ってます。
ぶっちゃけRailsがすごいのはActiveRecordなので、それさえ現役である限り終わっていないとも言えます。

次の言語何が来るかってのはいろいろあると思いますが、どんな環境になってもHTTPやデータベースの仕組みはしばらく変わることはないので、それさえ知ってればなんとかなるんじゃないのかなー。

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

1日目 ruby基礎,rails_scaffold(スキャフォールド)

文字コードの設定

ソースコードの文字コードをUS-ASCIIに設定する時は以下の3つのどの書きかたでも合ってる。
# coding: us-ascii
# encoding: us-ascii
# CODING: US-ASCII

変数と定数

rubyの場合、変数を定義する時は、小文字、定数を定義する時は、最初の文字が、大文字。以下に例を示す。
komozi=1
Oomozi=3.14

例外処理(begin rescue ensure)

beginの処理がエラーだった場合に、rescueの処理が実行される。ensureには、beginの処理がエラーでも、エラーじゃなくても処理される。

三項演算子

以下の2つの実行結果は同じである。

x = 10
y = x < 10 ? "A" : "B"

puts y
x = 10
y = nil
if x < 10
  y = "A"
else
  y = "B"
end
puts y

引数(*a)

以下のようにコードを書くと、実行結果が配列として出てくる。

def foo(*a)
  p a
end

foo(1,2,3)

繰り返し

繰り返しはeach,step,uptoメソットがある。
以下は例文。
・each

money = 1000
(1..10).each do
  (1..10).each do
    money = money + 1
  end
end

puts money

・step

money = 1000
rate = 1.1
(2001..2010).step(2) do |i|
  money = money * rate
end
puts money.to_i

 ・upto

money = 1000
rate = 1.1
2001.upto(2004) do
  money = money * rate
end
puts money.to_i

scaffold(スキャフォールド)

ruby on rails でアプリケションを作る際の便利ツール。本来、railsでは、モデル、コントローラー、ビュー、ルーティングを作る必要があるが、scaffoldを使えば、これらの作業をまとめて行って、簡単にアプリケーションの雛形を作ってくれる。

今日の授業の感想

今日はRubyの基礎を午前に行い、午後はscaffoldを用いて、フォームを作成した。午前は問題に出されたコードが、どのような処理を行うのかを学び、色んな発見があって理解が深まった。しかし、午後の授業に追いついて行けなかった。railsの環境構築も行ったが、〜をして、次に〜をしてくださいと言われても、どこで実行すればいいのかもわからず、(macでとか、mysql、railsとか)、専門用語も多いので、それが何の意味を指していて、なんでそれを実行する意味があるのかもわからず、自分の非力さを感じた。現在何をしているのかが全く分からなかった。事前課題はprogateで指定されたことを一通り行ったが、それだけではついていけなかった。授業の復習を行い、少しずつ理解を深めて行きたい。

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

2日目 ruby基礎,rails_scaffold(スキャフォールド)

文字コードの設定

ソースコードの文字コードをUS-ASCIIに設定する時は以下の3つのどの書きかたでも合ってる。
# coding: us-ascii
# encoding: us-ascii
# CODING: US-ASCII

変数と定数

rubyの場合、変数を定義する時は、小文字、定数を定義する時は、最初の文字が、大文字。以下に例を示す。
komozi=1
Oomozi=3.14

例外処理(begin rescue ensure)

beginの処理がエラーだった場合に、rescueの処理が実行される。ensureには、beginの処理がエラーでも、エラーじゃなくても処理される。

三項演算子

以下の2つの実行結果は同じである。

x = 10
y = x < 10 ? "A" : "B"

puts y
x = 10
y = nil
if x < 10
  y = "A"
else
  y = "B"
end
puts y

引数(*a)

以下のようにコードを書くと、実行結果が配列として出てくる。

def foo(*a)
  p a
end

foo(1,2,3)

繰り返し

繰り返しはeach,step,uptoメソットがある。
以下は例文。
・each

money = 1000
(1..10).each do
  (1..10).each do
    money = money + 1
  end
end

puts money

・step

money = 1000
rate = 1.1
(2001..2010).step(2) do |i|
  money = money * rate
end
puts money.to_i

 ・upto

money = 1000
rate = 1.1
2001.upto(2004) do
  money = money * rate
end
puts money.to_i

scaffold(スキャフォールド)

ruby on rails でアプリケションを作る際の便利ツール。本来、railsでは、モデル、コントローラー、ビュー、ルーティングを作る必要があるが、scaffoldを使えば、これらの作業をまとめて行って、簡単にアプリケーションの雛形を作ってくれる。

今日の授業の感想

今日はRubyの基礎を午前に行い、午後はscaffoldを用いて、フォームを作成した。午前は問題に出されたコードが、どのような処理を行うのかを学び、色んな発見があって理解が深まった。しかし、午後の授業に追いついて行けなかった。railsの環境構築も行ったが、〜をして、次に〜をしてくださいと言われても、どこで実行すればいいのかもわからず、(macでとか、mysql、railsとか)、専門用語も多いので、それが何の意味を指していて、なんでそれを実行する意味があるのかもわからず、自分の非力さを感じた。現在何をしているのかが全く分からなかった。事前課題はprogateで指定されたことを一通り行ったが、それだけではついていけなかった。授業の復習を行い、少しずつ理解を深めて行きたい。

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

【備忘録】form_withしたけど、redirectされないエラー

エラーについて

ユーザー登録できたけど、画面推移しないエラーにぶつかりました。

つまり、Usersコントローラーのcreateアクション内で、User.newして、@user.saveできてユーザー登録完了しているけど、redirect_to("/users/#{@user.id}")できないので、画面推移がされないエラーが起きました。

users_controller.rb
def create
    @user = User.new(
        name: params[:name],
        email: params[:email],
        image_name:"default_user.jpg",
        password: params[:password]
    )
    if @user.save
      session[:user_id] = @user.id
      flash[:notice] = "ユーザー登録が完了しました。"
      @current_user = @user
      redirect_to("/users/#{@user.id}")
    else
      render("users/new")
    end
  end

原因

form_withのurl先にlocal:trueがついていないことが原因でした。

users/new.html.erb
<%= form_with url: users_path do |form| %>

参照記事:「Rails 5.1のform_withを使ってうまくredirectできないあなたへ」https://kimuraysp.hatenablog.com/entry/2017/07/08/233754

解決策

local:trueをつけてフォームの送信ボタンを押したら、redirectされて、無事、画面推移されました。

users/new.html.erb
<%= form_with url: users_path, local: true do |form| %>

メモ:なぜform_with url: users_path, local: true do |form|だとredirect(画面推移)されるのか

結論:送信先がlocalであるべきところを、リモートにフォームの送信先が指定されていた点に原因があったのかもしれません。

localで開発していたので、フォームの送信先もlocalであるべきだったのかもしれません。ですが、local:trueをつけていないことから、デフォルトのフォームになっていたため、リモート + unobtrusive XHRが有効になっており、フォームの送信先がリモートになっていた可能性が高いです。

つまり、送信先がlocalであるべきところを、リモートにフォームの送信先が指定されていた点に原因があったのかもしれません。

local: trueを指定するとフォームのリモート + unobtrusive XHR送信が無効になります(デフォルトのフォームではリモート + unobtrusive XHRが有効になります)。
参照記事:https://techracho.bpsinc.jp/hachi8833/2017_05_01/39502

メモ

今回のエラーの原因を深掘りしていくには、Javascriptの知識が必要みたいなので、まずはprogateからやっていって、後ほど今回のエラーを振り返りたいと思います。

「unobtrusive XHR」とは、
unobtrusive = 「控えめな」 + XHR =「XMLHttpRequest」で、
「必控えめなXMLHttpRequest」という意味らしい。

・参照記事:
XMLHttpRequest についてのメモ https://qiita.com/sirone/items/412b2a171dccb11e1bb6

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

form_withしたけど、redirectされない原因と解決策

エラーについて

ユーザー登録できたけど、画面推移しないエラーにぶつかりました。

つまり、Usersコントローラーのcreateアクション内で、User.newして、@user.saveできてユーザー登録完了しているけど、redirect_to("/users/#{@user.id}")できないので、画面推移がされないエラーが起きました。

users_controller.rb
def create
    @user = User.new(
        name: params[:name],
        email: params[:email],
        image_name:"default_user.jpg",
        password: params[:password]
    )
    if @user.save
      session[:user_id] = @user.id
      flash[:notice] = "ユーザー登録が完了しました。"
      @current_user = @user
      redirect_to("/users/#{@user.id}")
    else
      render("users/new")
    end
  end

原因

form_withのurl先にlocal:trueがついていないことが、@user.saveできてユーザー登録完了しているけど、redirect_to("/users/#{@user.id}")できない原因でした。

users/new.html.erb
<%= form_with url: users_path do |form| %>

参照記事:「Rails 5.1のform_withを使ってうまくredirectできないあなたへ」https://kimuraysp.hatenablog.com/entry/2017/07/08/233754

解決策

local:trueをつけてフォームの送信ボタンを押したら、redirectされて、無事、画面推移されました。

users/new.html.erb
<%= form_with url: users_path, local: true do |form| %>

メモ:なぜform_with url: users_path, local: true do |form|だとredirect(画面推移)されるのか

結論:form_withの送信先がlocalであるべきところを、リモートに指定されていたからかもしれません。

自分はlocalで開発していたので、フォームの送信先もlocalであるべきだったのかもしれません。ですが、local:trueをつけていないことから、デフォルトのフォームになっていたため、リモート + unobtrusive XHRが有効になっており、フォームの送信先がリモートになっていた可能性が高いです。

つまり、送信先がlocalであるべきところを、リモートにフォームの送信先が指定されていた点に原因があったのかもしれません。

local: trueを指定するとフォームのリモート + unobtrusive XHR送信が無効になります(デフォルトのフォームではリモート + unobtrusive XHRが有効になります)。
参照記事:https://techracho.bpsinc.jp/hachi8833/2017_05_01/39502

メモ

今回のエラーの原因を深掘りしていくには、Javascriptの知識が必要みたいです。なので、まずはprogateである一定理解した後に、今回のエラーを振り返りたいと思います。

「unobtrusive XHR」とは、
unobtrusive = 「控えめな」 + XHR =「XMLHttpRequest」で、
「必控えめなXMLHttpRequest」という意味らしい。

・参照記事:
XMLHttpRequest についてのメモ https://qiita.com/sirone/items/412b2a171dccb11e1bb6

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

rails Basic認証

作成しているアプリケーションでbasic認証を使ってたので、備忘録として記載

gemのinstall

gemfileに下記を追加

gem 'dotenv-rails'

追加したら、bundle installを行う

環境変数の追加

gemfileやappなどがあるディレクトリに.envファイルを作成

BASIC_AUTH_USER='user名'
BASIC_AUTH_PASSWORD='password'

controllerの設定

controller.rb
before_action :basic_auth

    private
    def basic_auth
        authenticate_or_request_with_http_basic do |username, password|
            username == ENV["BASIC_AUTH_USER"] && password == ENV["BASIC_AUTH_PASSWORD"]
        end
    end

確認

以上のことが終了したらrails sで起動すると、下記のような認証を求めるものが出てくる
image.png

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

Pumaって結局何?

きっかけ

RailsでWEBアプリケーションを開発してリリースする際、PumaやUnicornを使ってNginxやらApachと組み合わせればいいということは調べてわかったけど、結局こういったコンポーネントはどういった役割を持っているのかはっきりわかっていなかったので、調べてみることにした

ウェブサーバー/アプリケーションサーバー

PumaやNginxは結局何なのか

まず、PumaとNginxが具体的にどういったものかという点について。Pumaはアプリケーションサーバー(app server)、Nginxはウェブサーバーといわれます。

アプリケーションサーバー

アプリケーションサーバーは実際に開発したアプリケーションを実行するソフトウェアです。基本的にはウェブサーバーからのリクエストを受け取りそれに対しレスポンスを返す働きをします。このとき、アプリケーションサーバーのみによってアプリケーションを動かすことも原理的には可能です。development環境で実行するときにはこのアプリケーションサーバーのみによって実行していることになります。

ウェブサーバー

ウェブサーバーはウェブサイトに対するリクエストに対する何らかの処理を行う働きをします。Railsを運用するときは、リクエストをアプリケーションサーバーに伝え、そのレスポンスをリクエストを送ってきたユーザーに返します。ただしウェブサーバーもそれ自身で動かないということはなく、静的なファイルを表示するだけであればウェブサーバーだけでも可能ですし、その方が表示速度が速くなります。また、SSL通信(httpsというプロトコルを用いて通信するとき)やリバースプロキシを用いる際にも必要になってくるソフトウェアです。

全体の流れ

最終的にどういうことかというと、ユーザからウェブサイトにリクエストが送られたとき、まずウェブサーバーがそのリクエストに応じてアプリケーションサーバーに対してこういうリクエストが来たよーと伝えます。このときに様々な処理をすることによってリクエストに対する処理を最適化することができるわけです。そしてアプリケーションサーバーが実際に処理を行ったものをウェブサーバーに伝え、それをウェブサーバーがユーザーに返すことによってユーザーの画面にウェブサイトが表示されるのでした。

参考リンク

https://www.justinweiss.com/articles/a-web-server-vs-an-app-server/

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

[スーパー小ネタ] railsでサーバー接続時にエラーが発生する

完全に小ネタです!
ただ、経験したことある方もいるかと思います。
結論から言うとパスには気を付けましょうということですね。はい....

今回起こった事象

cloud9でGithubからクローンしたリポジトリで開発を行おうとしていました。
とりあえずクローンしてサーバーに接続してみようと思うと下記エラーが発生しました

aws-test:~/clone_article $ rails server -b 0.0.0.0
Usage:
  rails new APP_PATH [options]

Options:
      [--skip-namespace], [--no-skip-namespace]            # Skip namespace (affects only isolated applications)
  -r, [--ruby=PATH]                                        # Path to the Ruby binary of your choice
                                                           # Default: /usr/local/rvm/rubies/ruby-2.4.1/bin/ruby
  -m, [--template=TEMPLATE]                                # Path to some application template (can be a filesystem path or URL)
  -d, [--database=DATABASE]                                # Preconfigure for selected database (options: mysql/postgresql/sqlite3/oracle/frontbase/ibm_db/sqlserver/jdbcmysql/jdbcsqlite3/jdbcpostgresql/jdbc)
                                                           # Default: sqlite3
      [--skip-yarn], [--no-skip-yarn]                      # Don't use Yarn for managing JavaScript dependencies
      [--skip-gemfile], [--no-skip-gemfile]                # Don't create a Gemfile
  -G, [--skip-git], [--no-skip-git]                        # Skip .gitignore file
      [--skip-keeps], [--no-skip-keeps]                    # Skip source control .keep files
  -M, [--skip-action-mailer], [--no-skip-action-mailer]    # Skip Action Mailer files
  -O, [--skip-active-record], [--no-skip-active-record]    # Skip Active Record files
      [--skip-active-storage], [--no-skip-active-storage]  # Skip Active Storage files
  -P, [--skip-puma], [--no-skip-puma]                      # Skip Puma related files
  -C, [--skip-action-cable], [--no-skip-action-cable]      # Skip Action Cable files.....

rails new APP_PATH [options]を初めて見たときは何だこれと思い、少し焦りました。
2、3回試し、同じエラーが発生したので、やり方が悪いのかと思い、少し調べました。

原因

今いるディレクトリーが Rails アプリのルートディレクトリーでないことが原因でした。
clone_article配下にrails-articleRecord/ があり、そこがRails アプリのルートディレクトリーでした。
ディレクトリを移動させるとうまくいきました。

aws-test:~/clone_article $ cd rails-record/
aws-test:~/clone_article/rails-record (master) $ rails server -b 0.0.0.0
=> Booting Puma
=> Rails 5.2.2 application starting in development 
=> Run `rails server -h` for more startup options
Puma starting in single mode...
* Version 3.12.0 (ruby 2.4.1-p111), codename: Llamas in Pajamas
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://0.0.0.0:8080
Use Ctrl-C to stop

パス間違いはRailsに限らず、起こりえることなので、よく確認してみると、エラーを確認する時間を短縮できるかもしれません。

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

半年間自動テストを利用して開発してみた感想

はじめに

以前自動テストの記事(自動テストの意義について考える)を投稿しました。
それから半年以上、自動テストを利用した開発を進めてきたため、今、どう思っているのかについて書いてみようと思います。

自動テストは必要か否か

自信を持って必要だと言い切ることができると感じています。
失うことより得ることが圧倒的に多いと感じているため、特にプロジェクトのスタートアップ時期において自動テストを利用しないという選択肢を取ることはほぼないのではないかなと。
ただ、既に運用・保守を開始しているようなプロジェクトなど、一部のケースではそこまで有用ではない可能性もあると感じています。

スタートアップ時期において有用と考える理由

  1. 積極的にロジックの変更を行うことができる
  2. 言語バージョンアップによる影響の検証を簡単に行うことができる

スタートアップ時期においては、特にプログラムや言語バージョンアップに対する変更リスクと戦っていくことになると考えています。
いかに柔軟に変更可能であるか、言語バージョンアップによる影響を簡単に把握できるか、という部分が最終的な開発スピードに大きく影響を及ぼしてくる。
自動テストを書いておくだけで、これらの影響の把握が簡単に行えるということは、非常に大きなメリットであると考えています。

運用・保守を開始しているサービスにおいて有用でない可能性がある理由

  1. 変更が入る可能性が低い部分に対してかけるコスト

運用・保守を開始しているサービスにおいては、上記のコストをどうみるか?が非常に重要になってくると思います。
サービスの8割の機能に変更が入らないものについて、すべての機能に対する自動テストを書く必要があるのか?という点においては、今後のサービスの展開などを考えて慎重に判断したほうが良いと思います。
変更が多い箇所のみに絞ってテストを記載するという方法もあると思うので、まずはなんのために自動テストを書くのか?という部分をしっかり意識しながら行うと良いかなと。
もちろん、時間をかけて全機能に対するテストを書く価値があると判断できるのであれば、書くに越したことはないと考えてます。

おわりに

思っていた以上に、自動テストによる恩恵は大きく、個人的にはもう自動テストを書かないという選択肢はないぐらいになっています。
どのレベルまでテストを書くのか?など、まだまだ課題は多くあるので、そのあたりに関しては今後も模索していければと思っています。

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

Rails 5.1.6 で Specified 'sqlite3' for database adapter, but the gem is not loaded. Add `gem 'sqlite3'` to your Gemfile (and ensure its version is at the minimum required by ActiveRecord). (Gem::LoadError) というエラーが出たら

TL;DR

sqlite3 gem のバージョンが新しすぎる可能性が高いです。バージョンを落とします。

Gemfile
gem 'sqlite3'

Gemfile
gem 'sqlite3', '~> 1.3.0'

に書き換えて、 bundle install を実行

具体的な症状と解決方法

Rails 5.1.6 で新しいアプリケーションを作成、つまり rails _5.1.6_ new test_app した後に、 Scaffold で CRUD な処理を作ろうとすると、

/Users/i.norifumi.homma/RailsApps/test_app% bin/rails g scaffold User email:string last_name:string first_name:string password:string
/Users/i.norifumi.homma/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/activerecord-5.1.6.1/lib/active_record/connection_adapters/connection_specification.rb:188:in `rescue in spec': Specified 'sqlite3' for database adapter, but the gem is not loaded. Add `gem 'sqlite3'` to your Gemfile (and ensure its version is at the minimum required by ActiveRecord). (Gem::LoadError)

のようなエラーが出ることがあります。
bundle install 時にはエラーは出ませんし、ちゃんと Gemfile にも Gemfile.lock にも sqlite3 が記載されています。

そんな時は、 Gemfile を開いて、 sqlite3 のバージョンを 1.3 系に落として、再度 bundle install します。
そうすると、今度は正しく実行できます。

/Users/i.norifumi.homma/RailsApps/test_app% bin/rails g scaffold User email:string last_name:string first_name:string password:string
Running via Spring preloader in process 17420
      invoke  active_record
      create    db/migrate/20190305084938_create_users.rb
      create    app/models/user.rb
      invoke    test_unit
      create      test/models/user_test.rb
      create      test/fixtures/users.yml
      invoke  resource_route
       route    resources :users
      invoke  scaffold_controller
      create    app/controllers/users_controller.rb
      invoke    erb
      create      app/views/users
      create      app/views/users/index.html.erb
      create      app/views/users/edit.html.erb
      create      app/views/users/show.html.erb
      create      app/views/users/new.html.erb
      create      app/views/users/_form.html.erb
      invoke    test_unit
      create      test/controllers/users_controller_test.rb
      invoke    helper
      create      app/helpers/users_helper.rb
      invoke      test_unit
      invoke    jbuilder
      create      app/views/users/index.json.jbuilder
      create      app/views/users/show.json.jbuilder
      create      app/views/users/_user.json.jbuilder
      invoke  test_unit
      create    test/system/users_test.rb
      invoke  assets
      invoke    coffee
      create      app/assets/javascripts/users.coffee
      invoke    scss
      create      app/assets/stylesheets/users.scss
      invoke  scss
      create    app/assets/stylesheets/scaffolds.scss

Rails 5.1.6 では sqlite3 のバージョン 1.4 系に対応していないようです。

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

Mac(Mojave)でRails起動すると Sorry, you can't use byebug without Readline エラー

背景

ローカルMac(Mojave)でRails4.6系。rubyを2.3系 -> 2.6系にあげて起動したところ以下のエラー発生。

   Sorry, you can't use byebug without Readline. To solve this, you need to
    rebuild Ruby with Readline support. If using Ubuntu, try `sudo apt-get
    install libreadline-dev` and then reinstall your Ruby.

やったこと

brewで入れたreadlineのバージョンが8.0になっているのがだめみたいだった。7.05にスイッチしたら動いた。

参考: https://github.com/deivid-rodriguez/byebug/issues/289#issuecomment-455963200

brewのバージョンの下げ方

この記事めっちゃわかりやすかった↓
Homebrewで旧バージョンのパッケージをインストールしたい

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

RailsでBootstrapを使うときにやることリスト

よく忘れるのでメモ。

  1. gemを追加
    gem 'bootstrap-sass', '3.3.7'
    (最新バージョンはここで確認できる↓
    https://rubygems.org/gems/bootstrap-sass/

  2. bundle install

  3. touch app/assets/stylesheets/custom.scss
    (CSSを正しい順序で表示させるため)

  4. custom.scssに以下を追加
    @import "bootstrap-sprockets";
    @import "bootstrap";

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

文字列を表として使う場合(例10×2など)のcount及びmapの使い方

下のように「a」が6つ「nil」が4つ文字列があった時
3番目から9番目(m[2..8])にaがいくつあるか。

m = [ "a" , "a" , "a" , "a" , "a" , "a" , nil , nil , nil, nil ]
m[2..8].count("a") => 4

文字列の中に文字列がある場合は

m = [[ "a" , "a" , "a" , "a" , "a" , "a" , nil , nil , nil , nil ],
     [ nil , nil , nil , nil , "a" , "a" , "a" , "a" , "a" , "a" ]]
#上段
m[0][2..8].count("a") => 4
#下段
m[1][2..8].count("a") => 5

*縦に調べたい場合、同じようにすると間違います。(失敗例)

(m[0][0]とm[0][1]でaの数を調べる)

#左から1番目の列
m[0..1][0].count("a") => 6

同じようにするとなぜか6になります。(上段のaの数になる)
*理由を知っている方がいたら教えてください。

mapを使って一段ずつ呼び出して、今回は一番左の列の情報が欲しいので、i[0]としています。

m.map{|i|i[0]}.count("a") => 1

もっと良い方法があったり、こういう考え方もあると思った人はコメントしていただけると助かります。

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

Railsでcsv出力したファイルをexcelで開いても文字化けしない方法

発生事象

RailsアプリケーションでCSV出力をしたファイルをExcelで開くと文字化ける。
理由はExcelがUTF-8のファイルをSJISで開こうとしてしまうため。

文字a化け.rb
def to_csv
  csv_column_name = %w(id 名前 メール)
  CSV.generate do |csv|
    csv << csv_column_name
    all.each do |user|
      csv << user.csv_column_values
    end
  end
end

方法1 BOM付きUTF-8でcsv出力する

bom付きにするとexcelがUTF-8で開く。
UTF-8のファイルをUTF-8として開くから文字化けない。

bom+utf8の方法.rb
def to_csv
  bom = "\uFEFF"
  csv_column_name = %w(id 名前 メール)
  CSV.generate(bom) do |csv|
    csv << csv_column_name
    all.each do |user|
      csv << user.csv_column_values
    end
  end
end
この部分.rb
bom = "\uFEFF"
この部分.rb
CSV.generate(bom) do |csv|

方法2 SJISにエンコードして出力する

sjisの方法.rb
def to_csv
  csv_column_name = %w(id 名前 メール)
  CSV.generate(encoding: Encoding::SJIS, row_sep: "\r\n", force_quotes: true) do |csv|
    csv << csv_column_name
    all.each do |user|
      csv << user.csv_column_values
    end
  end
end
この部分.rb
CSV.generate(encoding: Encoding::SJIS, row_sep: "\r\n", force_quotes: true) do |csv|

参考

https://qiita.com/wada811/items/8b73f633f77c0466e9da
https://qiita.com/ngron/items/60915083cb2bc3622c79

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

Railsで出力したcsvファイルをexcelで開いても文字化けしない方法

発生事象

RailsアプリケーションでCSV出力をしたファイルをExcelで開くと文字化ける。
理由はExcelがUTF-8のファイルをSJISで開こうとしてしまうため。

文字a化け.rb
def to_csv
  csv_column_name = %w(id 名前 メール)
  CSV.generate do |csv|
    csv << csv_column_name
    all.each do |user|
      csv << user.csv_column_values
    end
  end
end

方法1 BOM付きUTF-8でcsv出力する

bom付きにするとexcelがUTF-8で開く。
UTF-8のファイルをUTF-8として開くから文字化けない。

bom+utf8の方法.rb
def to_csv
  bom = "\uFEFF"
  csv_column_name = %w(id 名前 メール)
  CSV.generate(bom) do |csv|
    csv << csv_column_name
    all.each do |user|
      csv << user.csv_column_values
    end
  end
end
この部分.rb
bom = "\uFEFF"
この部分.rb
CSV.generate(bom) do |csv|

方法2 SJISにエンコードして出力する

sjisの方法.rb
def to_csv
  csv_column_name = %w(id 名前 メール)
  CSV.generate(encoding: Encoding::SJIS, row_sep: "\r\n", force_quotes: true) do |csv|
    csv << csv_column_name
    all.each do |user|
      csv << user.csv_column_values
    end
  end
end
この部分.rb
CSV.generate(encoding: Encoding::SJIS, row_sep: "\r\n", force_quotes: true) do |csv|

参考

https://qiita.com/wada811/items/8b73f633f77c0466e9da
https://qiita.com/ngron/items/60915083cb2bc3622c79

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

MySQLのGenerated Columnsまとめ with Rails

Geneterated Columnとは

  • 実カラムの値を計算した結果 を格納する専⽤のカラムを作成できる
  • 関数indexをシミュレートできる(生成列にindexを貼れるし、生成列で分割もできる)
  • MySQL5.7から使える。
  • Oracleの仮想列に近い。
  • CREATE TABLEまたはALTER TABLE文の中で使用できる。
  • [GENERATED ALWAYS] as (expression) の構文で作成する。

作成

CREATE TABLE triangle (
  sidea DOUBLE,
  sideb DOUBLE,
  sidec DOUBLE AS (SQRT(sidea * sidea + sideb * sideb))
);

データの挿入

INSERT INTO triangle (sidea, sideb) VALUES(1,1),(3,4),(6,8);

確認

mysql> select * from triangle;
+-------+-------+--------------------+
| sidea | sideb | sidec              |
+-------+-------+--------------------+
|     1 |     1 | 1.4142135623730951 |
|     3 |     4 |                  5 |
|     6 |     8 |                 10 |
+-------+-------+--------------------+
3 rows in set (0.01 sec)

何故 Geneterated Column を使うのか

  • データの保存用途ではなく、仮想生成した列は、
    照会を単純化し統一するための方法として使用できる。
    複雑な条件は、生成された列として定義することで、
    確実に同じ条件を使用するようにできる。

  • 格納された生成列は、その場で計算するのにコストがかかる
    複雑な条件のためのキャッシュとして使用できる。

  • Geneterated Columnは関数インデックスをシミュレートできる。
    Geneterated Columnを使用して関数式を定義し、
    それにインデックスを付けることもできる。

    • 生成された列にNOT NULL制約・UNIQUE制約をかけられる。
    • 生成された列で分割(partitioning)ができる。
    • 生成された列にインデックスが付けられている場合、クエリがその列を直接名前で参照していなくても、
      オプティマイザは列の定義と一致するクエリ式を認識し、
      クエリ実行中にその列のインデックスを適切に使用する
      https://dev.mysql.com/doc/refman/5.7/en/generated-column-index-optimizations.html

データの持ち方

  • Geneterated Columnは VIRTUAL または STOREDを指定することができる。
    デフォルトは VIRTUALである。
  • テーブル内に VIRTUAL と STORED は混在できる
  • どちらのタイプもセカンダリーインデックスを作成できる。
  • セカンダリーインデックスはどちらのタイプでもDiskに固定できる。

STORED

  • 列の値は、行が挿入または更新されたときに評価されて保管される。
  • ストレージを必要とする。
  • indexを貼れる。

VIRTUAL

  • SELECT時に都度計算される。
  • ストレージを必要としない。
  • MySQL 5.7.8から、計算後のデータに対してインデックスが貼れる

注意点

  • 生成された列式は、以下の規則に従う必要があり、
    式に許可されていない構成が含まれていると、エラーが発生する。

    • ストアドファンクション・ユーザー定義関数は不許可
    • ストアドプロシージャと関数パラメータは不許可
    • 変数(システム変数、ユーザー定義変数、およびストアドプログラムローカル変数)は不許可
    • サブクエリは許可されない
    • AUTO_INCREMENT属性は列の定義で使用できない
  • カラムとしては定義されているので、 SELECT * とかはできるが、
    Insert のように直接値を投入することはできない。

  • 式が宣言された列型とは異なるデータ型に評価された場合、
    宣言された型への暗黙的な強制は通常のMySQLの型変換規則に従って発生する。

  • 外部キー制約は仮想生成した列を参照できない。

Railsで実装する場合

テーブル作成時に追加する方法

class CreateTriangle < ActiveRecord::Migration[5.1]
  def change
    create_table :triangle do |t|
      t.integer :sidea
      t.integer :sideb
      t.virtual :sidec, type: :float,  as: "SQRT(sidea * sidea + sideb * sideb)"
      t.virtual :sided, type: :float,  as: "SQRT(sidea * sidea + sideb * sideb)", stored: true
    end
  end
end

テーブルの確認

mysql> show create table triangle;
+----------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table    | Create Table                                                                                                                                                                                                                                                                                                                                                                                    |
+----------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| triangle | CREATE TABLE `triangle` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `sidea` int(11) DEFAULT NULL,
  `sideb` int(11) DEFAULT NULL,
  `sidec` float GENERATED ALWAYS AS (sqrt(((`sidea` * `sidea`) + (`sideb` * `sideb`)))) VIRTUAL,
  `sided` float GENERATED ALWAYS AS (sqrt(((`sidea` * `sidea`) + (`sideb` * `sideb`)))) STORED,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+----------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.01 sec)

データの挿入

INSERT INTO triangle (sidea, sideb) VALUES(1,1),(3,4),(6,8);

確認

mysql> select * from triangle;
+----+-------+-------+---------+---------+
| id | sidea | sideb | sidec   | sided   |
+----+-------+-------+---------+---------+
|  1 |     1 |     1 | 1.41421 | 1.41421 |
|  2 |     3 |     4 |       5 |       5 |
|  3 |     6 |     8 |      10 |      10 |
+----+-------+-------+---------+---------+
3 rows in set (0.00 sec)

カラムとして追加

class AddColumnToTriangle < ActiveRecord::Migration[5.1]
  def up
    execute "ALTER TABLE triangle ADD COLUMN sidee float AS (
      CASE WHEN sidea > 2 THEN SQRT(sidea * sidea + sideb * sideb)
      ELSE NULL END
    )"

    add_index :triangle, :sidee, unique: true
  end

  def down
    remove_column :triangle, :sidee
  end
end

テーブルの確認

mysql> show create table triangle;
+----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table    | Create Table                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
+----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| triangle | CREATE TABLE `triangle` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `sidea` int(11) DEFAULT NULL,
  `sideb` int(11) DEFAULT NULL,
  `sidec` float GENERATED ALWAYS AS (sqrt(((`sidea` * `sidea`) + (`sideb` * `sideb`)))) VIRTUAL,
  `sided` float GENERATED ALWAYS AS (sqrt(((`sidea` * `sidea`) + (`sideb` * `sideb`)))) STORED,
  `sidee` float GENERATED ALWAYS AS ((case when (`sidea` > 2) then sqrt(((`sidea` * `sidea`) + (`sideb` * `sideb`))) else NULL end)) VIRTUAL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `index_triangle_on_sidee` (`sidee`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 |
+----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

確認

mysql> select * from triangle;
+----+-------+-------+---------+---------+-------+
| id | sidea | sideb | sidec   | sided   | sidee |
+----+-------+-------+---------+---------+-------+
|  1 |     1 |     1 | 1.41421 | 1.41421 |  NULL |
|  2 |     3 |     4 |       5 |       5 |     5 |
|  3 |     6 |     8 |      10 |      10 |    10 |
+----+-------+-------+---------+---------+-------+
3 rows in set (0.00 sec)

参考

MySQL 5.7にやられないためにおぼえておいてほしいこと
https://www.slideshare.net/yoku0825/mysql-57-53449734

13.1.18.8 CREATE TABLE and Generated Columns
https://dev.mysql.com/doc/refman/5.7/en/create-table-generated-columns.html

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

2019年3月7日以降はGoogle+ APIが使えない / rails + omniauth-google-oauth2でgoogleログインができなくなったら

Google+ API のサービス終了について

2019 年 3 月 7 日をもって、すべての Google+ API はサービスが終了します。 とのことです。

参考URL) https://developers.google.com/+/api-shutdown

これにより、Googleアカウントでログインしているサービスにも影響が出るようです。

対応方法

利用するAPIをこちらに差し替えると良いという記述がありました。
https://www.googleapis.com/oauth2/v2/userinfo

参考URL) https://github.com/zquestz/omniauth-google-oauth2/issues/340

ruby gemの omniauth-google-oauth2 のversion 0.6.0 では既に対応済みとのことです。

railsで既に導入している場合は、以下のようにgemをアップデートすると解消するかと思います。

bundle update 'omniauth-google-oauth2'

確認方法

Google APIsのダッシュボードから、Google+ APIを無効化した状態でもGoogleアカウントでログインできれば成功です。
omniauth-google-oauth2 の旧バージョンでは、Google+ API用のendpointを参照しているようですので、これで確認OKだと思います。

Google APIs) https://console.developers.google.com/apis/dashboard

image.png

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

2019年3月7日以降にrails+omniauth-google-oauth2でgoogleログインができなくなったら

Google+ API のサービス終了について

2019 年 3 月 7 日をもって、すべての Google+ API はサービスが終了します。 とのことです。

参考URL) https://developers.google.com/+/api-shutdown

これにより、Googleアカウントでログインしているサービスにも影響が出るようです。

対応方法

利用するAPIをこちらに差し替えると良いという記述がありました。
https://www.googleapis.com/oauth2/v2/userinfo

参考URL) https://github.com/zquestz/omniauth-google-oauth2/issues/340

ruby gemの omniauth-google-oauth2 のversion 0.6.0 では既に対応済みとのことです。

railsで既に導入している場合は、以下のようにgemをアップデートすると解消するかと思います。

bundle update 'omniauth-google-oauth2'

確認方法

Google APIsのダッシュボードから、Google+ APIを無効化した状態でもGoogleアカウントでログインできれば成功です。
omniauth-google-oauth2 の旧バージョンでは、Google+ API用のendpointを参照しているようですので、これで確認OKだと思います。

Google APIs) https://console.developers.google.com/apis/dashboard

image.png

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

deviseでパスワードの最低文字数を変更する方法。

パスワードを変更するには2種類の方法があります。

1 railsアプリのルートディレクトリ直下の~/configディレクトリにあるファイルを編集する方法です。

~/config/initializers/devise.rbにアクセスしてください。

config.password_length = 6..128

上記の部分がファイルの真ん中らへんにあるので、数値の部分を変更してください。

2 deviseを使用するモデルに直接記述する方法です。

例えば、user.rbに

devise :validatable, password_length: 10..128

このようにpassword_length: で指定してあげましょう。

最後に

自分でモデルにvalidates :password, length: { maximum: 8 }みたいに指定するとエラーの元になるのでやめましょう。僕はこれで1時間くらい溶かしました。

参考文献
https://github.com/plataformatec/devise/wiki/Customize-minimum-password-length

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

Google+API終了!devise✕omniauth-google-oauth2でGoogle+APIを利用せずにrailsのgoogleログインできるようにする

背景

自分が開発していたrailsアプリケーションでomniauth-google-oauth2のgemでgoogleログインを実装していたのですが
他の記事を参考に、Google+APIを有効にしてgoogle側の認証の設定をしていました。
参考:爆速ッ!! gem omniauth-google-oauth2 で認証させる
   [Rails] Facebook/Twitter/Googleでのユーザー登録をDevise & Omniauthを使って爆速で実装する
   など。

image.png

Google+APIの終了

ところが、Google+APIが終了ということでこれはまずいんじゃないか?
と思い調べてみたものの、なかなか解決策がみつからず。
Google+APIを無効化したら Invalid Credential と認証が無効であると怒られてしまう...

解決方法

どうしたものかと、omniauth-google-oauth2のgemのバージョンを上げてみたところ、

gem update 'omniauth-google-oauth2'
bundle install 'omniauth-google-oauth2'

無事Google+APIを無効にしてもログインできるようになりました。

定期的なgemの更新は大事ですね。

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

Rails~ルーティングのネストとform_forの関係~

form_tagだと...

form_tag ('/tweets', method: :post) do

form_tag ('tweets_path', method: :post) do

form_tag ({controller: :tweets, action: :create}, {method: :post}) do

form_forだと...

form_for (モデルクラスのインスタンス) do |f|

例えば。。。

form_for (@tweets) do |f|

form_tagではルーティングを示すものとHTTPリクエストが必要だが、form_forではモデルクラスのインスタンスを記述するだけで良い

ルーティングのネストとform_forの記述の関係

routes.rb
resources :users do
  resources :products do
    resources :reviews
  end
end

URLはこんな感じになる
/users/:id/product/:id/reviews

html.erb
form_for ([@users, @product, @review]) do |f|
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ruby クラス、インスタンス、継承

動作環境はMacです。

クラス

クラスとは車でいえば設計図のこと。
インスタンスは、設計図を元に作られる自動車そのもの。
ゆえにクラスの要素はもつが、個々のインスタンスでの特徴は違う。

オリジナルクラスの作成

構文

class クラス名
end

**実践**

car.rb
class Car #Carクラスを作成。頭文字は大文字
  def hello #メソッドの定義
    puts "Hello!"
  end
end

car = Car.new  #newメソッドでインスタンスを生成し、変数carに格納
car.hello #インスタンス変数の呼び出し
cae.rb
class Car
  def initialize(name) #インスタンスが作成(new)されると同時に実行
        puts "初期化されました"
    @name = name #インスタンス変数に引数nameの値を格納
  end

  def hello
    puts "Hello! I am #{@name}" #インスタンス変数はインスタンスの中であればどこからでも参照可能
  end
end

car = Car.new("Kitt") #initializeされ、引数”Kitt”がnameに渡される
car.hello

karr = Car.new("Karr")
car.hello
car.rb
初期化されました #newされたタイミングで出力される
Hello! I am Kitt
初期化されました
Hello! I am Kitt

クラスに所有されるインスタンスであればいくらでも呼び出すことができる。

アクセサ(インスタンス)メソッド

ゲッター、セッターとも呼ばれる。
インスタンス変数はクラスの外部から呼び出すことができないため、
呼び出せるように設定するメソッド。

accessor.rb
class Car
  def initialize(name)
    puts "初期化されました"
    @name = name
  end

  def hello
    puts "Hello! I am #{@name}"
  end
end

car = Car.new("Kitt")
car.hello

car.@name #クラス外部からインスタンス変を呼び出す

出力結果

ruby accessor.rb
accessor.rb:15: syntax error, unexpected tIVAR, expecting '('
car.@name
         ^

エラーになる。

accessor.rb
class Car
  def initialize(name)
    puts "初期化されました"
    @name = name
  end

  def hello
    puts "Hello! I am #{@name}"
  end

  def name #外部から読み取り可能なメソッドを定義
    @name
  end
end

car = Car.new("Kitt")
car.hello

puts car.name #呼び出し

出力結果

ruby accessor.rb
初期化されました
Hello! I am Kitt
Kitt #呼び出された
accessor.rb
class Car
  def initialize(name)
    puts "初期化されました"
    @name = name
  end

  def hello
    puts "Hello! I am #{@name}"
  end

  def name
    @name
  end

  def name=(value) #nameのを書き換えるメソッド。=も含まれる。スペースは開けない
    @name = value #インスタンス変数にvalueを代入
  end

end

car = Car.new("Kitt")
car.hello

puts car.name
car.name = "sisido" #nameを書き換え
puts car.name

出力結果

初期化されました
Hello! I am Kitt
Kitt
sisido #書き換わった!

アクセサメソッド2

attr_accessor

インスタンスメソッドを簡単に書き込みや読み込みができるようにするためのメソッド

accessor.rb
def name
  @name
end

def name=(value)
  @name = value
end

#この記述を簡単に書き換える

accessor.rb
class Car

  attr_accessor :name #この箇所にアクセサメソッドを記述

  def initialize(name)
    puts "初期化されました"
    @name = name
  end

  def hello
    puts "Hello! I am #{@name}"
  end


  #def name
    #@name
  #end

  #def name=(value)
    #@name = value
  #end

end

car = Car.new("Kitt")
car.hello

puts car.name
car.name = "sisido"
puts car.name

出力結果

初期化されました
Hello! I am Kitt
Kitt
sisido

読み取り専用メソッド

accessor.rb
class Car

  #attr_accessor :name
  attr_reader :name #読み取り専用のメソッド

  def initialize(name)
    #puts "初期化されました"
    @name = name
  end

  def hello
    puts "Hello! I am #{@name}"
  end

  #def name
    #@name
  #end

  #def name=(value)
    #@name = value
  #end

end

car = Car.new("Kitt")
#car.hello
#car.@name NG

puts car.name
#car.@name = "sisido" NG
#car.name = "sisido"
puts car.name
Kitt
Kitt

書き込み専用のメソッド

attr_accessor.rb
class Car

  #attr_accessor :name
  #attr_reader :name
  attr_writer :name #書き込み専用メソッドの記述

  def initialize(name)
    #puts "初期化されました"
    @name = name
  end

  def hello
    puts "Hello! I am #{@name}"
  end

  #def name
    #@name
  #end

  #def name=(value)
    #@name = value
  #end

end

car = Car.new("Kitt")
#car.hello
#car.@name NG

#puts car.name
#car.@name = "sisido" NG
car.name = "sisido" 
#puts car.name

クラス変数

クラス自体に値を保持することができる変数

実践

class_val.rb
class Car
  @@counter = 0 #クラス変数はここに記述
  def initialize(name)
    @name = name
    @@counter += 1 #インスタンスが作成されるごとにインクリメントされる
  end

  def hello
    puts "Hello! I am #{@name}.#{@@counter} instanse(s)."#この中にインスタンスの作成回数を記録
  end
end

kitt = Car.new("Kitt")
kitt.hello

karr = Car.new("Karr")
karr.hello

imawano = Car.new("imawano")
imawano.hello

出力結果

Hello! I am Kitt.1 instanse(s).
Hello! I am Karr.2 instanse(s).
Hello! I am imawano.3 instanse(s).

クラスメソッド

クラスから直接呼び出すことができるメソッド

実践

class_val.rb
class Car
  @@counter = 0
  def initialize(name)
    @name = name
    @@counter += 1
  end

  def hello
    puts "Hello! I am #{@name}.#{@@counter} instanse(s)."
  end

  def self.info #クラスメソッドの作成 selfをつける
    puts "#{@@counter} instance(s)"
  end
end

#kitt = Car.new("Kitt")
#kitt.hello

#karr = Car.new("Karr")
#karr.hello

#imawano = Car.new("imawano")
#imawano.hello

Car.info #クラスメソッドの呼び出し

出力結果

0 instance(s) #インスタンスは作成していないため0

インスタンスが作成された直後にクラスメソッドを呼び出す

class_val.rb
class Car
  @@counter = 0
  def initialize(name)
    @name = name
    @@counter += 1
  end

  def hello
    puts "Hello! I am #{@name}.#{@@counter} instanse(s)."
  end

  def self.info
    puts "#{@@counter} instance(s)"
  end
end

kitt = Car.new("Kitt")
#kitt.hello
Car.info

karr = Car.new("Karr")
#karr.hello
Car.info

imawano = Car.new("imawano")
#imawano.hello
Car.info

出力結果

1 instance(s)
2 instance(s)
3 instance(s)

1つのクラスをインスタンスが共通して使用していることがわかる。

クラスと定数

class_const.rb
class Car
  REGION = "USA" #定数の定義
  @@counter = 0
  def initialize(name)
    @name = name
    @@counter += 1
  end

  def hello
    puts "Hello! I am #{@name}.#{@@counter} instanse(s)."
  end

  def self.info
    puts "#{@@counter} instance(s). REGION: #{REGION}" ##クラスメソッド内で定数を使用
  end
end

kitt = Car.new("Kitt")
#kitt.hello
Car.info

karr = Car.new("Karr")
#karr.hello
Car.info

imawano = Car.new("imawano")
#imawano.hello
Car.info

puts Car::REGION #定数の呼び出し

定数の作成や呼び出しはクラス変数やインスタンス変数と違うので注意

**クラスの継承**

スーパークラス(親クラス)の振る舞いをサブクラス(子クラス)でも使用することができる

**実践**

sub_class.rb
class User
  def initialize(name)
    @name = name
  end

  def hello
    puts "Hello! I am #{@name}."
  end
end

class AdminUser < User #Userクラスの継承
  def admin_hello #AdminUserクラス内でメソッドを定義
    puts "Hello! I am #{@name} from AdminUser."
  end
end

iwamano = User.new("iwamano")
iwamano.hello

sansiro = AdminUser.new("sansiro") 
sansiro.hello #AdminUserクラスのでUserクラスのメソッドを使用
sansiro.admin_hello #AdminUserクラス内のメソッドを使用

出力結果

Hello! I am iwamano.
Hello! I am sansiro.
Hello! I am sansiro from AdminUser.

Userクラス(親クラス)からAdminUserクラスのメソッドを呼び出すことはできない

sub_class.rb
iwamano = User.new("iwamano")
iwamano.hello
iwawano.admin_hello

出力結果

Hello! I am iwamano.
sub_class.rb:19:in `<main>': undefined method `admin_hello' for #<User:0x007fbc6a19f4c8 @name="iwamano"> (NoMethodError) #エラーが返る

オーバーライド

親クラスの持つ振る舞いを子クラスで上書きや追加をすることができる機能

実践

sub_class.rb
class User
  def initialize(name)
    @name = name
  end

  def hello
    puts "Hello! I am #{@name}."
  end
end

class AdminUser < User
  def admin_hello
    puts "Hello! I am #{@name} from AdminUser."
  end

  def hello
    puts "Admin!" #親クラスのhelloメソッドに上書き
  end
end

iwamano = User.new("iwamano")
iwamano.hello #子クラスのhelloメソッドの呼び出し
#iwamano.admin_hello

sansiro = AdminUser.new("sansiro")
sansiro.hello
sansiro.admin_hello

出力結果

Hello! I am iwamano.
Admin! #親クラスのhelloメソッドは呼び出されず、子クラスのhelloメソッドが呼び出されている
Hello! I am sansiro from AdminUser.

オーバーライドは親クラスの修正を加えることなく子クラスに同名のメソッドを記述することで、上書きや追加をすることができる。

クラスの確認

クラス名.superclassで確認することができる。

例)Integerクラス

irb(main):002:0> Integer.superclass
=> Numeric
irb(main):003:0> Numeric.superclass
=> Object
irb(main):004:0> Object.superclass
=> BasicObject
irb(main):006:0> BasicObject.superclass
=> nil #BasicObjectクラスが大元の親クラスとなるため、nilが返る
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

rails create、updateアクションでの小ネタ(エラーハンドリング�について)

はじめに、、、

そもそもエラーハンドリングとは、、、

エラーハンドリングとは、プログラムの処理中に処理が妨げられる事象が発生した際、その処理をエラーとして対処する処理のことである。例外処理とも呼ばれる。

とのことです。
今回はこれについて話していきます。

railsでエラーハンドリングを行う

railsでエラーハンドリングを行わなければならなくもっとも使用頻度で高いものでいうとmodelのcreateアクションだと思います。

article_controller.rb
def create
  @article = Article.create(article_params)
  redirect_to articles_path
end

上のような書き方をしていると、もし仮にarticleがバリデーションの設定等の原因で新しいレコードをcreate出来なかった場合、エラーがでてそこで処理が止まってしまいます。

ローカル開発なら問題ないですが、実務環境で処理が止まってしまうと数分で何百万もの損失を出してしまう可能性があります。
そこで、エラーハンドリングを行います。

そしてエラーハンドリングをやった時のcreateアクションが↓です。

article_controller.rb
def create
  #@articleと言う変数に値を入れる
  @article = Article.new(article_params)
  if @article.save #保存できるか?
    #保存に成功した時はarticleのindexアクションにリダイレクト
    redirect_to articles_path
  else
    #保存に失敗したときはarticleのnewアクションにリダイレクト
    render :new
  end
end

このように、値をseveする時にseveできているかの条件式(if文)を挟む事で、
値が作成されずエラーが出て処理が停止してしまう事は無くなります。

最後に

railsではscaffoldなどのrails g コマンドを使ってビューファイルを生成した時は、自動でエラーハンドリングは行われていますが、
自分でsave処理を行う時などは、気をつけてコーディングしましょう!

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

【Rails5】DBからデータが削除されたことをテスト自動化するときの観点たち

Introduction

Railsでデータを削除する機能をRSpecのSystem Testでテストしたときのメモ。
「削除対象のレコードが削除されていること」を確認するためにいくつかの観点から検証を実施してみました。

【観点1】対象を削除すると検索してもNotFound

[id=1のレコードを削除処理]
expect{Model.find(1)}.to raise_exception(ActiveRecord::RecordNotFound)

まずは素直に削除した対象を検索するとNotFoundになる検証。find_byを使っても同じように検証できます。
あんまり考えにくいですが、idupdateされた場合でも検証は通ってしまいます。

ちなみに今回の記事で一番メモしておきたかったのはこのraise_exceptionの書き方。
expect{}とブロックで記述しないといけないのがかなりつまずきポイントでした。

【観点2】対象を削除するとwhere検索しても0件

expect(Model.where(id: 1).count).to eq 1
[id=1のレコードを削除処理]
expect(Model.where(id: 1).count).to eq 0

次はwhereを使ってひっかかった数が0になることでレコードが削除されたことを検証する方法です。この場合でも、idupdateされたケースは検証は通ってしまいます。
whereなので1件に絞る必要はなく、例えばアソシエーションの全ての子要素を消す時の検証などでは使いやすい気がします。「User1に紐づく全Itemを削除」の場合はexpect(Item.where(user_id: 1).count).to eq 0とすれば検証ができます。
一方で、whereだとデータ量が多いとテスト実行の性能が悪くなったりするのかな。

【観点3】対象を削除するとレコード数が減る

count = Model.all.count
[いずれか1レコードを削除処理]
expect(Model.all.count).to eq (count - 1)

1レコード削除されれば総数が1減る、という検証です。これ単体では何が消えたのか定かではありませんが、観点1・2と合わせることで「idupdateされた」可能性をなきものとできる気がします。

Conclusion

【観点1】or【観点2】でおおよそやりたいことはできました。【観点3】も合わせ技として複合すれば、間違ってほかのレコードも消していないことなども検証できるので安心安全です。

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

Rails〜環境構築〜

Command Line Tools

gccというコンパイラが入っていてRuby内部でこのコンパイラを使用する

Homebrew

MacOS上でソフトウェアの管理を行うもの
パッケージ管理とは、追加、更新、削除を行うこと

rbenv

Homebrew経由でインストールする
必要に応じてRubyのバージョンを切り替えることを可能にする
ターミナル
rbenv rehash
gemはRubyのバージョンごとに管理されている
gemをインストールした時にそのgemのコマンドをそのRubyのバージョンで使えるようにするためのコマンド

ruby-build

Rubyのバージョンをインストールすることを可能にする

RubyGems

Rubyのプラクイン管理機能みたいなもの

Gem

Rubyを便利に扱うためのアプリケーション
Rubyのバージョンごとに管理されている
ターミナルでそれぞれのgemが持つコマンドを実行するという形で使用する

Bundler

gemの1つなのでRubyGems経由でインストールする
プロジェクトごとに使用するgemを決めたり、バージョンを決めたりする
RubyGemsより柔軟なイメージ
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails〜ユーザー管理機能の実装〜

deviseの導入

gemfile
gemfileに記述する
gem 'devise'
ターミナル
bundle install
rails s

deviseの設定ファイル
rails g devise:install

deviseに基づいたUserモデル
rails g devise user
rake db:migrate

deviseによるデフォルトのview
rails g devise:views

usersコントローラは普通に
rails g controller users

ニックネームを登録項目の追加

ターミナル
nicknameカラムの追加
rails g migration AddNicknameToUsers nickname:string
rake db:migrate

※間違えた場合は
rake db:rollback

追加したカラムをストロングパラメータとして受け取る

application_controller.rb
    before_action :configure_permitted_parameters, if: :devise_controller?

    def configure_permitted_parameters
      devise_parameter_sanitizer.permit(:sign_up, keys: [:nickname])
    end

※sign_upはアクション名

他には
ログインしていないユーザーに投稿させないようにする
ヘッダー部分にログイン・新規登録ボタンを作る
登録画面にニックネームを登録するフォームを追加する

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

【備忘録】Railsを使って開発を始めたいと思った時の読み物

これは何か

  • Railsで開発を始めようとした時の環境構築あたりのtipsをまとめたもの

参考情報

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