パラメータから受け取って生成したModelで単純にループして登録するだけの処理ならControllerで実装しちゃっても良いけど、もうちょっと実装のボリュームがありそうだったのでModelに実装したい。
Modelに実装したいときどういうIFにしたら良いか参考にしたかったのでGitLabを調べみた。eachでループしてActiveRecord#saveを実行しているだろうと仮定して「save」という文言でgrepした。そのうちの一つを紹介する。
ソースコード貼る
一応行っておくとGitLabはオープンソースになっているGithubのクローンプロジェクトですね。
リポジトリ
https://github.com/gitlabhq/gitlabhq
app/models/users_project.rb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
# Add users to project teams with passed access option # # access can be an integer representing a access code # or symbol like :master representing role # # Ex. # add_users_into_projects( # project_ids, # user_ids, # UsersProject::MASTER # ) # # add_users_into_projects( # project_ids, # user_ids, # :master # ) # def add_users_into_projects(project_ids, user_ids, access) project_access = if roles_hash.has_key?(access) roles_hash[access] elsif roles_hash.values.include?(access.to_i) access else raise "Non valid access" end UsersProject.transaction do project_ids.each do |project_id| user_ids.each do |user_id| users_project = UsersProject.new(project_access: project_access, user_id: user_id) users_project.project_id = project_id users_project.save end end end true rescue false end |
UsersProject#add_users_into_projects に一括登録処理を見つけた。複数projectに複数userを一括で登録する処理みたい。
UsersProject.transactionでトランザクション管理されてる。例外が発生してもちゃんと登録がロールバックされますね。
戻り値はbooleanのtrue/false。例外が発生したらfalseでそれ以外はtrueで返します。project_access 〜 の部分で権限をチェックしてますね。権限がなければ例外を投げてrescueでfalseで返してる。
呼び出し元にはどういう理由でfalseなのかっていうのは返さないのか。
app/models/project_team.rb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
def add_user(user, access) add_users_ids([user.id], access) end def add_users(users, access) add_users_ids(users.map(&:id), access) end def add_users_ids(user_ids, access) UsersProject.add_users_into_projects( [project.id], user_ids, access ) end |
#add_users_into_projects の呼び出し元を探る。別モデルであるProjectTeamモデルから呼ばれてる。特筆すべきことはない。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
# Shortcut to add users # # Use: # @team << [@user, :master] # @team << [@users, :master] # def << args users = args.first if users.respond_to?(:each) add_users(users, args.second) else add_user(users, args.second) end end |
さらに#add_user, #addusersの呼び出し元を調べると同じProjectTeamモデル内から呼ばれている。
<<メソッドで実装してた。メソッド名を<<にすることでコメントにあるように、@team << [@user, :master] という呼び方が出来るのでArray#<<と同様に、「チームにユーザーを追加」っていう挙動が直感的に分かる。 addなんちゃらってメソッドを書きたい場合は、メソッド名を<<にすると良さそう。今後やってみよう。 結局 ProjectTeam#<< を呼び出している箇所は見つからなかった。。。まあいいか。

原田 敦

最新記事 by 原田 敦 (全て見る)
- Rails Engineでブログ機能追加するgemを作る - 2015年3月15日
- WEBエンジニア一人だけでサービスを作りきる方法-夫婦のための自動ごはん予定お知らせサービス「GoHaaan」制作でやったこと - 2015年3月7日
- CentOS6でMariaDBのDynamic Columnsを試してみた - 2015年2月28日