[Rails] そうだ、コントローラで引数を取ろう [ActionArgs]

Rails ではコントローラに渡ってくる値は

```rb
def show
  @user = User.find(params[:id])
end
```

このように取れる。
しかし、 [ActionArgs](https://github.com/asakusarb/action_args) という gem を導入すると

```rb
def show(id)
  @user = User.find(id)
end
```

こんな感じで取れるのだ。

post で渡される値もこの通り。

```rb
class UsersController < ApplicationController
  def create(user)
    @user = User.new(user)
    ...
  end
end
```

別になくても死にはしないが[使いたい理由](https://gfx.hatenablog.com/entry/2017/06/24/115822)はある。

ただし、他の gem との併用で問題が出てくる場合もある。
[cancancan と一緒に使う](http://tech.grooves.com/entry/2016/01/22/105639)
Strong Parameters 周りの問題なので、大体の gem は問題ないはず。

さらに副作用として、初めて見た人を

1. Rails ってこういう書き方もできるのか！
2. 他のプロジェクトでもやってみよ。
3. できない :cry:
4. 何故に？

と困惑させる力を持つ。

……が使ってて気分がいいので使いたい。

## [使い方](https://github.com/asakusarb/action_args#actionargs)
```rb
class UsersController < ApplicationController
  # params[:id] を必要とする
  def show(id)
    @user = User.find id
  end

  # params[:page] はあってもなくてもいい
  def index(page = nil)
    @users = User.page(page).per(50)
  end

  # ↑よりも↓の書き方がおすすめと README には書いてある

  # params[:page] はあってもなくてもいい
  def index(page: nil)
    @users = User.page(page).per(50)
  end

  # params[:post_id], params[:comment] を必要とする
  def create(post_id:, comment:)
    post = Post.find post_id
    if post.create comment
      ...
  end
end
```

params 変数は消えたわけではないので、今まで通りのコードもちゃんと動くはず。

## [Strong Parameters](https://github.com/asakusarb/action_args#strongparameters---permit)

Strong Parameters は二つのやり方がある。

### permit メソッドを呼び出す

```rb
class UsersController < ApplicationController
  def create(user)
    @user = User.new(user.permit(:name, :age))
    ...
  end
end
```

### 宣言する
- コントローラと対になっているモデルに対して行うとき。

例: `UsersController <-> User`

```rb
class UsersController < ApplicationController
  # User モデルの Strong Parameters
  permits :name, :age

  # user は ActionArgs によって確認されたものが渡される
  def create(user)
    @user = User.new(user)
  end
end
```

- コントローラと対になっていない時

`model_name` を指定する。

```rb
class MembersController < ApplicationController
  # User モデルの Strong Parameters
  permits :name, :age, model_name: 'User'
end
```

## [Filter](https://github.com/asakusarb/action_args#filters)
`before_action` 系の処理。
普通に書ける。

```rb
class UsersController < ApplicationController
  before_action :set_user, only: :show

  def show
  end

  private
    # params[:id] が id にセットされる
    def set_user(id)
      @user = User.find(id)
    end
end
```

## [Scaffold Generator](https://github.com/asakusarb/action_args#the-scaffold-generator)
ActionArgs 流に生成してくれるようになる。

```rb
class UsersController < ApplicationController
  before_action :set_user, only: [:show, :edit, :update, :destroy]
  permits :name, :age, :email

  # GET /users
  def index
    @users = User.all
  end

  # GET /users/1
  def show
  end

  # GET /users/new
  def new
    @user = User.new
  end

  # GET /users/1/edit
  def edit
  end

  # POST /users
  def create(user)
    @user = User.new(user)

    if @user.save
      redirect_to @user, notice: 'User was successfully created.'
    else
      render action: 'new'
    end
  end

  # PUT /users/1
  def update(user)
    if @user.update_attributes(user)
      redirect_to @user, notice: 'User was successfully updated.'
    else
      render action: 'edit'
    end
  end

  # DELETE /users/1
  def destroy
    @user.destroy

    redirect_to users_url
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_user(id)
      @user = User.find(id)
    end
end
```