Spring Boot(Java)からRuby on Railsに乗り換えたから、Railsの好きなところをまとめた

#Spring Bootもいいやつだったけど、もうRuby on Railsが本命なんだ！

Javaからプログラミングを始めました。仕事に生かすことが目的だったけれど、
今は主にWebサービスを趣味で作っています。個人開発やベンチャーではRuby on Railsが主流と聞いていたのでもともと興味はありました。けれど、Javaも素人級なのに別の言語を学習するのはコストが高すぎるし、Webサービスとして形を作れればなんでもいいと思っていました。

なので、Javaフレームワークでも、シンプルに素早く開発ができて新しい、Spring Bootを使用して開発をしていました。　
一通りSpring Bootで開発〜公開まで行い、やりたいことはなんとなくできるようになっていました。
それでも、Ruby On Railsは気になっていたけれど、一方、Spring Bootにもある程度愛着が湧いていて、
人と違うフレームワーク使ってるのもなんだかちょっとかっこいいとか思い、このまま使い続ける予定でした。

これが3週間ほど前。

作りたいWebサービスを思いつき、今回はさくっと2〜3週間を目標にリリースしようと開発を始めました。
しかし、まさかのTwitterログイン認証ではまりました。もちろん今までもうまく動かず悩むことはあったので、色々と調べていたのだけど、Spring Boot(Spring Social と　Spring　Securityを連携させたい)を使用したTwitter認証の情報が英文含めても極端にすくない。どれを試してもうまくいかなかった。ここで2日使った。（8時間くらい）
正直処理の過程を理解できていない部分も多かったです。一から公式リファレンスを調べて、独力で実装する方法もあったと思います。独自機能の実装にはそれくらい時間かけても良いと思うのだけど、Twitter認証のような一般的な部品は正直コピペで実装したいという思いが強かった。ふとRuby on Railsで調べてみると、いくらでもサンプルが出てきて、実装もシンプルでした。

その後もRailsについて調べて、個人でWebサービスをスピード感をもって実装したい。という要望には、
明らかにRuby On Railsが向いていると考えました。
学習コストはかかるけれど数ヶ月スパンでみれば乗り換えた方が効率は上がるはずなので、
サービス開発は一旦中止して、乗り換えることにした。ついでにVScodeからAtomに乗り換えた。


#Ruby on Railsの勉強歴
約2週間ほど（40〜50時間）勉強しました。
電車の中と昼休みにドットインストールのRuby編とRuby on Railsチュートリアルを読んで、
帰宅後に手を動かして実装する、といった感じです。

Ruby on Railsチュートリアは飛ばし飛ばし、通読　→　実装　→　通読のざっくり3週しました。
ここからは、実際にサービスを作りながらわからない部分を勉強する予定です。

#Spring Boot vs Ruby on Rails
Ruby on Railsは最高なやつだった！

##無料のドキュメントやサンプルが圧倒的に多い。
めちゃくちゃ大事。とくに独学者として気軽に聞ける人がいないので、
Google先生の活躍が死活問題になります。

###Spring Boot:
Spring BootはWebにまとまった情報がありません。
なので参考書を探しましたが、選択肢は4種類ほどで書評も少なく良し悪しがわかりませんでした。
近所の本屋にも取り置きがなかったのでわざわざ新宿まで行って買いました。

###Ruby on Rails:
今回学習に1円もつかっていません。
Ruby on Railsチュートリアルしかり、初心者レベルであれば、オンラインの学習サービスや
検索でだいたい学べるので、非常にとっつきやすいフレームワークでした。
サンプルも豊富なので、今後の開発のスピードアップに期待できます。

##実行環境のセットアップが楽
###Spring Boot:
Javaインストールして、パス通して、Mavenインストールして、パス通して、
諸々、使い始めるまで1時間程かかりました。初学者は挫折するレベルです。

###Ruby on Rails:
MAC使ってますがどうやって作った忘れたくらい簡単でした。
※忘れました。


##プロジェクト作成が楽
###Spring Boot:
[Spring Initializer](https://start.spring.io/)にアクセスしてパッケージを作成します。
GroupとArtiface項目に何入れたら良いかいまだに分からないし選択項目が多い。

###Ruby on Rails:
コンソールからrails newで開発が速攻始められる。DBの種類もオプションで指定できるらしい。

##フォルダー構成のデフォルトが優秀
###Spring Boot:
デフォルトではとくに何もできないので、自分で配置ルール決めてフォルダーを作る必要があります。
当初はベストプラクティスがわからず、これでいいのかな〜と気になりつつも自己流MVCでなんとかやってました。

ぽちぽち作ったソースフォルダー：
<img width="303" alt="スクリーンショット 2018-06-10 19.09.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/162167/f77348f8-655c-ced4-8f6b-68015b7e0f6d.png">

###Ruby on Rails:
Rails newでパッケージ作成すると、も,model,view,configなど用途に分けたフォルダーが自動的に作成されます。
ソースコード配置に気を使わなくても、デフォルト従えば整理されるので初心者には助かります。
自動生成してくれるのもお決まりの単純作業が省けていいです。

自動生成されたフォルダーソースフォルダー：
<img width="150" alt="スクリーンショット 2018-06-10 19.07.00.png" src="https://qiita-image-store.s3.amazonaws.com/0/162167/a230b760-a72b-4b15-60e5-4a94c0c0b264.png">

##依存パッケージ管理がシンプル
###Spring Boot:
pom(Maven)で管理します。
記載項目はこのような感じ。

```java:pom.xml
 <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
 </dependency>
```
###Ruby on Rails:
gemファイル で管理します。
記載項目は同じ。若干シンプルでしょうか。

```ruby:Gemfile
gem 'rails', '~> 5.2.0'
```

##URLのマッピングがわかりやすい
###Spring Boot:
コントローラーでURLとビューのマッピンングや値の受け渡しを行います。
複数ファイルに渡ってマッピングが記載されるので、どのURLがどのビュー、コントローラーと
関連づいているのか多々見失います。`value = "/"`が対応するURLで`mav.setViewName("index")`
でindexという名前のテンプレート（HTMLファイル）探して表示します。この他にも色々な定義方法があります。

```java:indexController.java
@Controller
public class indexContoroller{

@RequestMapping(value = "/", method = RequestMethod.GET)
public ModelAndView showIndex (ModelAndView mav){
    mav.setViewName("index");
	return mav;
    }   
}
```

###Ruby on Rails:
URLマッピングはrouters.rbに定義します。
Spring BootのコントローラーからURLのマッピングだけ切り取った形になります。一覧できるので可読性が高いですね。 `get  '/help', to: 'static_pages#help'`は'/help'がURLで、
'static_pages#help'が実行する処理のあるクラスです。

```ruby:routers.rb
Rails.application.routes.draw do
  get  '/help', to: 'static_pages#help'
```

```ruby:static_pages_controller.rb
class StaticPagesController < ApplicationController
 
    def help; 
    #hogehoge
    end

ends
```

##DBの存在を忘れるくらい抽象化されている

###Spring Boot:
DB使用したい時は、データベース用意して、テーブル作成して、
そのあとにDB接続用のクラス数個を用意する必要があります。
操作は抽象化されていますが、データ書き込めるようにするまでのステップ数は少なくないです。

ちょっと長いですがMemberテーブルを操作するために用意したクラスを記載しています。
`Member.java`が`Memberテーブル`と対応して、データを受け取ります。
`MemberRepository.java`でクエリをカスタマイズ可能です。

実際のアクセスは、使用したいクラスで`@Autowired MemberRepository repository;`
でレポジトリーインスタンスを作成して、`repository.findById(id);`のように使用します。


`JpaRepository<Member, Integer>`はテーブルの主キーの型を指定しないとエラーが発生します。

```java:MemberRepository.java
public interface MemberRepository extends JpaRepository<Member, Integer> {
    public Member findByUsername(String username);
    public boolean existsByUsername(String username);
}
```

テーブルに対応したクラス：

```java:Member.java
Entity
@Table(name = "member")
public class Member implements UserDetails {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    // private Long userid;
    private int userid;

    @Column(nullable = false, unique = true)
    private String username;

    @Column(nullable = false)
    private String password;

    @Column(nullable = false)
    private String displyname;

    public Member() {
        super();

    }

    public String getDisplyname() {
        return displyname;
    }

    public int getUserid() {
        return userid;
    }

    public void setDisplyname(String displyname) {
        this.displyname = displyname;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return null;
    }

    @Override
    public String getPassword() {
        return this.password;
    }

    @Override
    public String getUsername() {
        return this.username;
    }

    public String getMail() {
        return this.displyname;
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }

}
```
###Ruby on Rails:
` rails generate model "テーブル名" content:text`
のようにコマンドを実行するとテーブルと操作に必要なクラスが自動的に生成されます。
以下のようにいきなりDBから読み出し、書き込みができてしまいます。

```ruby
m = "テーブル名".new
m.find_by()`
```
ここまで一度もDBに直接接続していません。RailsではついDBの存在を忘れそうになります。


##Gemが優秀
###Spring Boot:
Spring Bootで画像アップロード機能実装しましたが結構大変でした。
HTMLとJSでアップロードとバリデーション書いて、
受け取ったあとはファイルのパスをDBに入れて、ファイルはローカルに保存する。
という処理を一から書く必要がありました。

###Ruby on Rails:
画像アップロードに関しては、CarrierWaveというGemがあり、
Spring Bootの1/3ほどの処理で実装できます。
Springにも便利な機能はたくさんありますが、Railsの方が
Web開発に関しては上手な印象です。

##Webサーバーバンドル
###Spring Boot:
実はSpring BootもTomcatバンドルしているので、これは引き分け。
デフォルトのポート80だと、MACのローカルでは起動できないので、ポート番号指定して起動する必要あり。

###Ruby on Rails:
ポートは3000番がデフォルトのようだから何もしなくてOK

###その他　Ruby on Rails good point
- データ受け取った後のバリデーションが簡単
- テンプレートエンジンがシンプル（Eruby vs Thymelefe）
- HTMLのコンポーネント化が簡単
- JS,CSSの読み込みが楽（アセットパイプライン）
- フォームからデータ書き込みまでの流れが綺麗
- Ajax簡単。JSほぼ書かなくていい
- コントローラーからビューへの値の受け渡しを自動でやってくれる。
- コントローラーを作るとビューも自動的に作成される

#まとめ
Railsは地味な作業はバックグラウンドで面倒みてくれる部分が多く、
プログラム書いているんだけど、パズルやゲームしているような感覚になりました。
Spring Bootについては、色々手続きを踏んだ上で機能を実装できるので、チームでかっちりとした
大きなアプリケーション作るには向いているのかなと思いますが、個人開発レベルでは
そのかっちりさは必要ないなーというのが現在の結論です。