railsでマルチチェックボックスになった子テーブル登録、更新を実現したい
Activeレコードではないオブジェクト(Hoge)の項目をマルチチェックボックスでUserの子テーブルHogeUserに登録、更新させたい
- UserクラスとHogeUserクラスは一対多の親子クラスです。
- HogeオブジェクトはActiveRecordでは無くid,nameといった項目を持っています。
- Userクラスの保存と共にHogeでチェックが入った項目をHogeUserレコードに複数登録したいです。(チェックが入ってないのは登録されないようにしたいです。)
- バージョンアップ前のruby1.9.3,rails3.2を使ってます。
まだ中途半端で動いてないですが以下が現在の実装です。
Userクラス
class User < ActiveRecord::Base
has_many :hoge_users
attr_accessible ::hoge_users_attributes
accepts_nested_attributes_for :hoge_users
validates_associated :hoge_users
validate :should_have_at_least_one_hoge_user
def should_have_at_least_one_hoge_user
errors.add(:hoge_users, 'should have at least one.') if hoge_users.empty?
end
HogeUserクラス
class HogeUser < ActiveRecord::Base
belongs_to :hoge
attr_accessible :hoge, :name, :hoge_id
validates :hoge_id, :presence => true
end
UsersControllerクラス
class UsersController < ActionController::Base
def new
@user = User.new(User::DEFAULT, :as => :admin)
respond_to do |format|
set_objects_for_new_view
~
def create
@user = User.new(params[:user], :as => :admin)
hoge_ids = params[:hoge_users_attributes]
unless hoge_ids == nil
hoge_ids.each do |hoge_id|
@user.hoge_users.new(:hoge_id => hoge_id)
end
end
respond_to do |format|
if @user.save
~
def set_objects_for_new_view
@hoges = GET::Zone.all
@hoge_users = @user.hoge_users.new
_form.html.erb
<%= f.fields_for :hoge_users do |hoge_user_f| %>
<%= render :partial => 'hoge_user_form', :locals => {:f => hoge_user_f} %>
<% end %>
_hoge_user_form.html.erb
<% @hoges.each do |hoge| %>
<tr>
<%= hoge.name %>
<%= check_box_tag 'hoge_users_attributes[]', hoge.id %>
</tr>
<% end %>
ググってみましたがActiveレコード以外から取得する例がありませんでした。HogeをActiveRecordに入れる必要がありますでしょうか?⇒回答で解決。コード修正済み
【追記】上記のようにコード修正すると登録までできるようになりました。ただチェックボックス未選択時のバリデーションが動いてくれません(hoge.idが空)。
何か間違っている箇所が有ったりしますでしょうか?⇒回答で解決。コード修正済み
【追記2】詳細更新画面について
- 頂いたご回答で登録処理は動作するようになりました。続いて詳細更新画面が上手く動きません。
- 詳細でHogeUserに登録されていたものはチェックがついてる状態にしたいです。
- チェックボックスを外したら削除されるようにしたいです。
- 新しくチェックを入れたものは追加されるようにしたいです。
UsersControllerクラス
詳細出す前にHogeオブジェクトを取るようにしました。
class UsersController < ActionController::Base
def show
@user = target_user
@hoges = GET::Zone.all
respond_to do |format|
format.html { render :partial => 'show' }
~
def update
@user = target_user
respond_to do |format|
if @user.update_attributes(params[:user], :as => :admin)
~
_show_user.html.erbビュー
check_boxにhoge_idを指定して登録されていたものはチェックがついてる状態になりました。
"hoge_accounts_attributes"=>{"hoge_id"=>"チェックボックスで選択したhoge.id", "0"=>{"id"=>"登録されたTBL.id"}}}
paramsは↑のものが渡るようになりました。update前にhoge.idを取得してhoge_users.newする形になるのでしょうか?
<th>ホゲ</th>
<td>
<%= f.fields_for :hoge_users do |hoge_user_f| %>
<% @hoges.each do |hoge| %>
<%= hoge.name %>
<%= hoge_user_f.check_box :hoge_id, {:name =>'user[hoge_users_attributes][hoge_id]'}, hoge.id %>
<% end %>
<% end %>
</td>
</tr>
Userクラス
削除にはallow_destroy
オプションつけて_destroyというパラメータを渡さなければいけないとあったのですがチェックを外すと_destroyパラメータが付く形にしたいです。
class User < ActiveRecord::Base
accepts_nested_attributes_for :hoge_users, :allow_destroy => true