質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

解決済

1回答

1420閲覧

【Ruby on Rails】関連モデルの最新行を取得したい

pecchan

総合スコア555

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

0グッド

0クリップ

投稿2017/05/08 01:24

編集2017/05/08 01:25

お世話になっております。

社員を取得する際に、所属する部署も一緒に取得したいです。

所属部署が頻繁に変わるため、所属マスタに開始日を持たせて、最新の部署のみ取得したいです。

テーブルは以下のようになっています。

社員マスタ(employee)
id
name

所属マスタ(emp_group)
id
employee_id
group_name
start_date

社員コントローラで以下のようにしましたが、

@test = EmpGroup.where(employee_id: 社員ID).order(:start_date).reverse_order.limit(1) logger.debug @test.to_s

デバッグすると
EmpGroup::ActiveRecord_Relation:0x0000000ad1d2b0
と出て日付が取得出来ていません。いや取得出来ているのかも分かりません。。。

そもそも、このような場合は、コントローラではなく
モデル(社員)上で定義しておくべきかと思うのですが、どうでしょうか?
いずれにせよ具体的な記述が分かりません。

どうぞアドバイス宜しくお願い致します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

まず、式はあっています。しかし
厳密には、debugの表示段階では日付は取得できていません
以下理屈を説明します。
ActiveRecord_Relationは
SQLを生成するのに必要な情報を持っておくclassです。
Modelにallをするかjoinsとかwhereとかorderを繋げるとActiveRecord_Relationになります。
これに、さらにjoinsとかwhereとかorderを繋げる事ができ、
Railsがここだ!というタイミングにArelというライブラリを使いSQLに変換し実行します。
DBの情報はこの時に取得されます。

そもそも、モデル層
普通逆なんじゃないかなーと思います。
まあ、一人の社員が複数の所属になるのなら話は違いますが…。

社員マスタ(employee)
id
name
emp_group_id#現在の所属のID

所属マスタ(emp_group)
id
group_name

所属履歴(emp_group_log)
id
employee_id
emp_group_id
emp_group_name#所属の部署?名がしょっちゅう変わる場合とか
start_date

とやるのがいいのではないのでしょうか?

モデル(社員)上で定義しておくべきかと思うのですが、どうでしょうか?

その発想、素晴らしいです。
そういった場合has_oneとdelegate(委譲)を使って
例えば社員modelに

ruby

1has_one :org_group ,->{order 'start_date desc'},class_name: 'EmpGroupLog' 2delegate :start_date,:emp_group_name,to: :org_group,prefix: true

とかやると

ruby

1Employee.first.org_group_start_date 2Employee.first.org_group_emp_group_name

で取得できます。

で、railsはこのdeligateをよく使うので
groupがダブりまくってうざいので本当は

ruby

1#所属マスタ(emp_group) 2id 3name 4#所属履歴(emp_group_log) 5id 6employee_id 7emp_group_id 8name#所属の部署?名がしょっちゅう変わる場合とか 9start_date

みたいに、極力シンプルなnameにする方がいいと思います。
VBとかだと逆に習いますが...
DRYじゃないですよね

投稿2017/05/08 02:54

編集2017/05/08 02:59
moke

総合スコア2241

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

pecchan

2017/05/08 05:17

moke様 いつも有難う御座います。 >そもそも、モデル層 普通逆なんじゃないかなーと思います。 >まあ、一人の社員が複数の所属になるのなら話は違いますが…。 そうです。一部の社員は兼任します。 アドバイスいただいた設計、 社員マスタに現在の所属のIDを持たせて、 所属マスタは、単体にし、 所属履歴マスタで履歴管理する方法、いいですね! こちらだと、所属履歴を登録する際、セレクトボックスの入力が1つで済みますね! こちらの方法に変更しようと思います。 また、ActiveRecord_Relationの原理も教えていただき有難う御座いました! 今回もたくさん勉強になりました、有難う御座います。
moke

2017/05/08 06:10 編集

いえいえ pecchan様の質問は答えやすいのでw >>一部の社員は兼任します。 >>こちらの方法に変更 えーと、それだと兼任を記述できないのでは…。 emp_groupとemployeeに中間テーブルを貼るのもありですが。 主従を作っておかないと、SQLのサガで集計が二倍になったりするんですよね 中間テーブルに主従を管理するcloumnを作るか おもに主従両方使う 主はemployeeにidで持たせ、所属履歴に、on_deteみたいなcolumnを作って管理 おもに主のみ使う みたいな感じですかね、悩みますね
pecchan

2017/05/08 06:19

moke様 度々有難う御座います。 あ、そうですね。最新1つだけになってしまう・・・。 じっくり考えてみます^^ 有難う御座います。
pecchan

2017/05/09 02:58

moke様 お世話になっております。 ご報告です。 詳細は割愛させていただきますが、今回は仕様の関係から当初通りの 社員マスタと所属マスタでいくことになりました。 有難う御座いました。
moke

2017/05/09 03:02

そうですか。 まあ、仕様ならしようがないですね delegateはそれでも使えると思うので試してみてください。 has_one :org_group ,->{order 'start_date desc'},class_name: 'EmpGroup' delegate :start_date,:emp_group_name,to: :org_group,prefix: true みたいなことはできると思うので
pecchan

2017/05/09 03:26

moke様 はい。ちょうど教えていただいたdelegateを試していました(^o^) 仕様なんですが、 質問を簡潔にするため、所属マスタ:group_name と記載しましたが、 実際、所属マスタが持つのは、部署id、課id、グループidの組み合わせなんです。 所属単体よりも、部、課、グループそれぞれを個別に管理する必要があるためでした。 有難う御座いました。
moke

2017/05/09 04:15 編集

なるほど、これは業務プログラムのさがですね 一応、アイデアとして 完全な包含関係(真の部分集合)ならば、部署id、課id等は絞り込みだけに使い reef node(末端)のidだけ保存するという方法もあります。 また、sqlは集合論に基づいて記述されている割に包含関係弱いのですが 一応mceachen/closure_treeというgemがありまして、これで包含関係を管理すると 包含関係を維持したままactive_recordできるんです。 これらを組み合わせると、構造が変化しても、コードを直す必要がななく 絞り込み、合計ができちゃうんです。 さらに、部や課の付け替えも割と簡単にできます。 よかったら、暇な時にでも見てみてください。
pecchan

2017/05/09 05:37

moke様 有難う御座います。 色んな方法があるんですね。 今の私には無理そうです・・・。 moke様の知識の広さ、深さに感嘆致します。 はい。いったん落ち着いてからまた勉強します。 この度は有難う御座います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問