プログラミングスクールのチーム開発でECサイトを作成している際、
どこのリンク先から遷移したかでインスタンス変数を変えたい・・・
というような場面がありました。
その時に2パターンの方法があったので、備忘録として残します。
【環境】
Ruby: 2.5.7
Rails: 5.2.4
使用した中で関係するgem:devise(顧客、管理者を作成)
前提条件
- 管理者側のページで注文一覧を表示する際、下記のように設定したい。
- トップページから遷移 => 本日作成された注文一覧
- 顧客の詳細ページから遷移 => その顧客の注文一覧
- ヘッダーの注文一覧ボタンから遷移 => 全ての注文一覧
テーブル
schema.rb
create_table "orders", force: :cascade do |t|
t.integer "user_id", null: false
(略)
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "users", force: :cascade do |t|
(略)
end
モデル(アソシエーション)
user.rb
has_many :orders, dependent: :destroy
order.rb
belongs_to :user
ルート
namespace :admins do
get '', to: 'products#top'
resources :users, only: [:index, :show, :edit , :update]
resources :orders, only: [:index, :show, :update]
end
実装パターン①:遷移元をコントローラで取得する
参考にした記事:Railsで遷移元のコントローラーとアクションを取得する
admins/orders_controller.rb
def index
path = Rails.application.routes.recognize_path(request.referer)
# path[:controller]で遷移元コントローラーを、path[:action]でアクションを取得
if path[:controller] == "admins/products" && path[:action] == "top"
@orders = Order.where(created_at: Date.today)
elsif path[:controller] == "admins/users" && path[:action] == "show"
@orders = Order.where(user_id: path[:id])
else
@orders = Order.all
end
end
これで、3パターンの変数を持たせることができました。
ただ、この内容だと【トップ画面からヘッダーの注文履歴ボタンを押した】際、
トップ画面から遷移したと判断されてしまいます。
そのため、最終的には下記の方法で実装を行いました。
実装パターン②:リンク元にパラメーターを付ける
遷移元のリンクページには下記の通りパラメータを持たせました。
admins/products/top.html.erb
<%= link_to "本日の注文件数", admins_orders_path(order_sort: 0) %>
admins/users/show.html.erb
<%= link_to "注文一覧", admins_orders_path(order_sort: 1) %>
そしてコントローラ側では、持ってきたパラメーターで変数を振り分け
admins/orders_controller.rb
def index
case params[:order_sort]
when "0"
@orders = Order.where(created_at: Date.today)
when "1"
@user = User.find(params[:user_id])
@orders = @user.orders
else
@orders = Order.all
end
end
これによって①の問題は解消されました。
まとめ
- ①の方法であればコントローラ側で一目見れば分岐条件がわかりやすいと思うが、状況に応じた実装が求められる。
- ①の方法を応用すれば、updateやdestroyアクションのリダイレクト先などを分岐させることも可能。