I'm using rails 4.2. I have created a form that submits to a particular action in my controller. Here is the beginning of the form code and the controller definition:
view.html.erb
<div id="account-booking" class="tab-pane">
<%= form_for #booking_info, url: { action: 'book' } do |b| %>
<fieldset class="group column-1">
<legend>Booking Preference for <%= Rails.configuration.x.app_settings.year %></legend>
<div class="group column-full radio-list">
<%= label_tag('Select Room Type') %>
<% #available_rooms.each do |rt| %>
<div class="radio-item">
<!--
<%= b.radio_button :room_type_id, rt.id, :class => 'rb_room_type inline', :onclick => fetch_room_info_path(:id => rt.id), :remote => true %>
<%= b.radio_button :room_type_id, rt.id, :class => 'rb_room_type inline', :onclick => 'render_room_info('+ rt.id.to_s + ');' %>
-->
<%= b.radio_button :room_type_id, rt.id, :class => 'rb_room_type inline' %>
<%= content_tag :span, rt.name %>
<a data-toggle="tooltip" data-placement="right" title="<%= rt.description %>">
<%= image_tag "tooltip.png", :class=>"tooltip-icon" %>
</a>
</div>
<% end %>
<%= b.label :roommate_preference, 'Roommate Preference' %>
<%= b.text_area :roommate_preference, :class => 'form-control' %>
<div class="account-checkbox-options">
<%= b.label :is_flexible, class: 'checkbox inline' do %>
<%= b.check_box :is_flexible %>
I am flexible with regards to my room choice.
<% end %>
</div>
</div>
<!--
<div id="estimated-due" class="group column-2">
</div>
-->
</fieldset>
<fieldset class="group column-2 account-preferences">
<legend>Your Room Information for <%= Rails.configuration.x.app_settings.year %></legend>
<div class="group column-1">
<div class="group column-full add-tabbing">
<%= label_tag('Selected Room:') %>
<span><%= #booking_info.room_type.blank? ? '<No Room Selected>' : #booking_info.room_type.name %></span>
</div>
<div class="group column-full add-tabbing">
<%= label_tag('Assigned Room:') %>
<span><%= #booking_info.assigned_type.blank? ? '<No Room Assigned>' : #booking_info.assigned_type.name %></span>
</div>
</div>
<div class="group column-2">
<div class="group column-full add-tabbing">
<%= label_tag('Total Due:') %>
<span ><%= number_to_currency(#booking_info.total_due.blank? ? 0.00 : #booking_info.total_due) %></span>
</div>
<div class="group column-full add-tabbing">
<%= label_tag('Current Balance:') %>
<span><%= number_to_currency(#booking_info.outstanding_balance.blank? ? 0.00 : #booking_info.outstanding_balance) %></span>
</div>
</div>
<% unless #booking_info.assigned_type.blank? %>
<div class="group column-full">
<h2>Assigned Room Information</h2>
</div>
<% end %>
</fieldset>
<div class="account-buttons">
<%= b.submit 'Submit', class: 'btn btn-danger' %>
<%= link_to 'Cancel', '/pages/home', class: 'link-button-cancel' %>
</div>
<% end %>
</div>
account_controller.rb
def book
#booking = PersonRoom.new(booking_params)
#requested_room = RoomType.find(params[:person_room][:room_type_id])
#booking.room_type = #requested_room
if update_booking #booking
redirect_to :controller => 'account', :action => 'view'
else
render('view')
end
end
All of this works beautifully when there is no PersonRoom record (e.g. if I'm doing an insert). However, if I try to update the record, using the same exact form / action (because both the view and the action are exactly the same regardless of whether i'm inserting or updating), I get an error when I click "Submit":
No route matches [PATCH] "/account/book"
This makes no sense. I'm on the exact same page. I just used all of this code to create the record, so the route clearly exists (because it calls /account/book). Now I want to update but suddenly the route doesn't match? And it never even breaks into the code because it doesn't call the controller action. This makes zero sense to me. Hope someone can help.
I winced when looking over your code, here's how I'd have done it:
#config/routes.rb
resources :rooms do
resources :bookings #-> url.com/rooms/:room_id/bookings/new
end
#app/controllers/bookings_controller.rb
class BookingsController < ApplicationController
before_action :set_room
def new
#booking = room.bookings.new
end
def create
#booking = room.bookings.new booking_params
#booking.save
end
def update
#booking = room.bookings.update booking_params
end
private
def set_room
#room = Room.find params[:room_id]
end
def booking_params
params.require(:booking).permit(:x, :y, :z)
end
end
This setup is pretty standard with Rails (IE resourceful routes):
Browsers request pages from Rails by making a request for a URL using
a specific HTTP method, such as GET, POST, PATCH, PUT and DELETE. Each
method is a request to perform an operation on the resource. A
resource route maps a number of related requests to actions in a
single controller.
Observing this principle would likely resolve your "weird" routing errors due to their cohesion with the other aspects of the Rails system.
For example:
#app/controllers/accounts_controller.rb
class AccountsController < ApplicationController
#-> this shouldn't have a "book" action unless necessary. Your case is not necessary
end
--
The problem you have is that you're not adhering to the Rails' convention of keeping your system object-orientated.
The importance of this is huge; Rails is designed to make it as simple as possible to CRUD (create read update destroy) data objects. These objects are built from database data in the "models":
I use this picture a lot - it shows how Rails should work. You build objects in your Models which you manipulate in your controllers. The views show it all to the user.
Thus, when you're looking at your code, I would keep it as simple as possible:
#app/models/room.rb
class Room < ActiveRecord::Base
has_many :bookings
has_many :users, through: :bookings
belongs_to :type
end
#app/models/booking.rb
class Booking < ActiveRecord::Base
belongs_to :room
belongs_to :user
end
#app/models/user.rb
class User < ActiveRecord::Base
has_many :bookings
has_many :rooms, through: :bookings
end
This will allow you to call the following:
#room = Room.find 1
#room.bookings #-> collection of bookings per room
You could also do something like the following (simple) for the views:
#app/views/bookings/new.html.erb
<%= form_for #booking do |f| %>
<%= f.text_field :x %>
<%= f.text_field :y %>
<%= f.text_field :z %>
<%= f.submit %>
<% end %>
I found the problem. It was something really stupid. I had the following line in my route.config:
match ':controller(/:action(/:id))', :via => [:get, :post]
I just needed to change this to:
match ':controller(/:action(/:id))', :via => [:get, :post, :patch, :put, :delete]
Now it handles updates (i.e. patch / put)
Related
I am working on a hotdesking app where the users would check_availability (check_availability.html.erb) of the desks based on the date range chosen and choose from a list of available desk (new.html.erb) before it gets saved in the database.
How can i use the form input in check_availability and use it under my 'new' method?
bookings_controller.rb
class BookingsController < ApplicationController
def index
end
def check_availability
end
def new
#booking = Booking.new(booking_params)
#booking.date_range(params[:book_from], params[:book_to])
end
def create
end
def show
end
private
def booking_params
params.permit(:book_from, :book_to, :wing, :section, :number, :user_id)
end
end
booking.rb
class Booking < ApplicationRecord
belongs_to :user, optional: true
belongs_to :desk, optional: true
accepts_nested_attributes_for :desk, allow_destroy: true
cattr_accessor :current_user
attr_accessor :book_from, :book_to
def check_availability
counter = 0
Booking.all.each do |b|
current_date = Date.today
booked_start_date = b.book_from
booked_end_date = b.book_to
if b.user_id == current_user.id && current_date <= booked_end_date && booked_start_date <= current_date
counter += 1
end
end
puts counter
end
def date_range(book_from, book_to)
a = []
a.push(book_from)
a.push(book_to)
puts a
end
routes.rb
Rails.application.routes.draw do
devise_scope :user do
authenticated :user do
root 'bookings#index', as: :authenticated_root
end
unauthenticated do
root 'devise/sessions#new', as: :unauthenticated_root
end
end
devise_for :users
resources :desks
post '/users/:user_id/bookings/:id', :to => 'bookings#show'
post '/users/:user_id/bookings/new', :to => 'bookings#new'
resources :users do
resources :bookings do
collection do
get :check_availability
end
end
end
end
check_availability.html.erb
<div class="container-fluid">
<div class="row">
<div class='col-sm-6 col-sm-offset-3'>
<h1>Check Availability</h1><hr />
</div>
<div class='col-sm-6 col-sm-offset-3'>
<%= form_tag new_user_booking_path, multipart: true do %>
<div class='form-group'>
<span class='not-bold'><%= label_tag :book_from, "Book From" %>: </span></br>
<span class='date-select'><%= date_select :book_from, class: 'form-control' %></span>
</div>
<div class='form-group'>
<span class='not-bold'><%= label_tag :book_to, "Book To" %>: </span><br />
<span class='date-select'><%= date_select :book_to, class: 'form-control' %></span>
</div>
<%= submit_tag "Check Availability", class: "btn" %>
<% end %>
</div>
<br />
<div class='col-sm-6 col-sm-offset-3'>
<br />
<hr />
<button type="button" class="button">
<%= link_to "My Bookings", authenticated_root_path %>
</button>
<button type="button" class="button">
<%= link_to "Book Desk", new_user_booking_path(current_user) %>
</button>
</div>
It took me lots of tries to figure this out!
I realised it was a routing issue. The form should be doing a GET instead of a PUT request.
I changed the form_tag route in my check_availability.html.erb file to <%= form_tag(new_user_booking_path, method: "get", class: "bookings") do %> and i can now access the form inputs through the controller with params.
I've been working with app for pizzeria where customers could order pizzas through their website. I currently working with the product page where I try to submit products to shopping cart through ajax, but I'm really stuck. I haven't been able to build a shoppingcart which would accept product-id, product-size-id, extra-toppings as an array and quantity. I decided to try to go with session-store where all the order-row ids are stored and on menu page every product has a form where user could add product, size and quantity to shoppingcart but I keep getting this error in server logs:
Started POST "/order_row" for ::1 at 2015-08-03 11:18:21 +0300
Processing by OrderRowsController#create as JS
Parameters: {"utf8"=>"✓", "order_row"=>{"product"=>"1", "size"=>"0", "quantity"=>"2"}, "commit"=>"Tilaa"}
Completed 500 Internal Server Error in 2ms (ActiveRecord: 0.0ms)
ActiveRecord::AssociationTypeMismatch (Product(#70158072501800) expected, got String(#70158039566200)):
app/controllers/order_rows_controller.rb:4:in `create'
I have models Product, ProductCategory, Order, OrderRow and my session stores order-row-ids as mentioned. My menu page is actually product_categories#show -view where products belonging to that category are listed.
#order_rows_controller.rb
class OrderRowsController < ApplicationController
respond_to :html, :js
def create
#orow = OrderRow.new(order_rows_params)
if #orow.save
session[:order_row_ids] << #orow.id
flash[:notice] = "Lisättiin ostoskoriin!"
else
flash[:error] = "Tuotteen lisääminen ostoskoriin epäonnistui."
redirect :back
end
end
def update
#orow = OrderRow.find(params[:id])
if #orow.update_attributes(params[:order_row])
flash[:notice] = "Ostoskori päivitetty."
else
flash[:error] = "Ostoskorin päivitys epäonnistui."
end
end
def destroy
#orow.find(params[:id]).destroy
flash[:notice] = "Tuote poistettu onnistuneesti"
end
private
def order_rows_params
params.require(:order_row).permit(:product, :size, :quantity) #, :extras => []
end
end
ProductCategories-controller
class ProductCategoriesController < ApplicationController
before_action :set_product_category, only: [:edit, :update, :destroy]
respond_to :html, :js
def index
#product_categories = ProductCategory.all
end
def show
#product_category = ProductCategory.friendly.find(params[:id])
#product_categories = ProductCategory.all
#products = #product_category.products
#order_row = OrderRow.new(order: nil, product: nil, size: nil, extras: nil, quantity: nil)
end
And menu-page in product_categories/show.html.erb
#product_categories#show -view
<!--- category descriptions -->
<div class="container">
<% #products.each do |product| %>
<div class="col-sm-6 col-md-4">
<div class="product well">
<h3><%= product.name %></h3>
<span><%= product.description %></span>
<p class="prices">
<%= price(product.normal_price) %> | <%= price(product.plus_size_price) %> | <%= price(product.lunch_price) %>
</p>
<br>
<div id="form-<%= product.id %>">
<%= simple_form_for #order_row, :url => url_for(:controller => 'order_rows', :action => 'create'), remote: true do |f| %>
<%= f.hidden_field :product, :value => product.id %>
<h5>Koko</h5>
<div style="padding-left: 13px">
<%= f.input :size, collection: OrderRow.sizes, as: :radio_buttons, label: false, item_label_class: "radio-inline", item_wrapper_tag: false %>
</div>
<h5>Määrä</h5>
<div style="width: 8%; padding-left: 13px;">
<%= f.input :quantity, as: :string, label: false %>
</div>
<p>
<%= f.submit "Tilaa", class: "btn btn-success btn-lg" %>
</p>
<% end %>
</div>
</div>
</div>
<% end %>
</div>
Create.js.erb in order_rows#create action
#create.js.erb
$("#form-<%= params[:product] %>").load(document.URL + "#form-<%= params[:product]");
Associations:
#order_row
belongs_to :order
belongs_to :product
#product
belongs_to :product_category
has_one :campaign_producte
belongs_to :dish_type
#product_categories
has_many :products
has_many :campaign_products
has_many :product_extras
has_many :dish_types, through: :products
#product_extra
belongs_to :product_category
Link to github-repo: https://github.com/casualCodeAndDesign/ravintolamammamia
What's the reason for this server error and why it doesn't store my order_row to the database?
ActiveRecord::AssociationTypeMismatch (Product(#70158072501800)
expected, got String(#70158039566200))
You need to change
<%= f.hidden_field :product, :value => product.id %>
to
<%= f.hidden_field :product_id, :value => product.id %>
and product to product_id in create.js.erb and order_rows_params
I want to query multiple tables. For example in posts table there is a user_id linked to users id. While showing every post, I also want to display the picture of the user. My approach is this, but there is a problem. #user.picture method is undefined.
<% #programs.each do |post| %>
<%= #user = User.where("id = post.user_id") %>
<li class="one-third column">
<div class="wrapper">
<div class="postThumb"><img src="<%= #user.picture %>" /></div>
<div class="postDetails">
<%= link_to "#{ post.title.upcase! }".html_safe, all_posts_path, :class => "postTitle" %>
<p><%= truncate post.details, :length => 90 %></p>
</div>
</div>
</li>
<% end %>
Program Controller:
class ProgramController < ApplicationController
def index
#programs = Program.all
end
User model:
class User < ActiveRecord::Base
attr_accessible :password, :username, :oauth_token, :provider, :uid, :oauth_expires_at, :picture, :email, :name, :location, :gender, :updated_at, :is_admin
has_many :posts
has_one :program
has_many :programdetails, :through => :program
end
Program model:
class Program < ActiveRecord::Base
attr_accessible :details, :title, :user_id
belongs_to :user
has_many :programdetails
end
Try this instead, in the controller:
#programs = Program.includes(:user) # this will return all programs and related users in
# 2 database queries rather than N+1 queries
Then in the view:
<div class="postThumb"><img src="<%= post.user.picture %>" /></div>
Also, you can use image_tag instead.
Finally, you can probably change your post title link to:
<%= link_to post.title.upcase, all_posts_path, :class => "postTitle" %>
#user = post.user. Rails association will give back the associated user by itself.
And to correct above, syntactically, #user = User.find(post.user_id)
try changing this: #user = User.where("id = post.user_id")
into this: #user = User.where(id: post.user_id).first
or even better: #user = post.user as suggested by kiddorails
There is a much easier way to do this using the relations you have already defined:
Programs Controller
def index
#programs = Program.
includes(:user). # eager load user relation to avoid n+1
all
end
View
<% #programs.each do |post| %>
<li class="one-third column">
<div class="wrapper">
<div class="postThumb"><img src="<%= post.user.picture %>" /></div>
<div class="postDetails">
<%= link_to "#{ post.title.upcase! }".html_safe, all_posts_path, :class => "postTitle" %>
<p><%= truncate post.details, :length => 90 %></p>
</div>
</div>
</li>
<% end %>
I'm working on a shows when a store was last visited. I want to be able to update multiple stores at once if they were all visited on the same day.
I think I have most of the code but I can't figure out how to get rid of the mass assignment error
Can't mass-assign protected attributes: date_visited(1i), date_visited(2i), date_visited(3i)
{"utf8"=>"✓",
"_method"=>"put",
"authenticity_token"=>"/yr8kLOyrTRGPfG1f/I5ilY/QB6GUx9IhQj6WiBaibM=",
"store_ids"=>["4",
"5"],
"visit"=>{"date_visited(1i)"=>"2012",
"date_visited(2i)"=>"11",
"date_visited(3i)"=>"14"},
"commit"=>"Save Visit"}
Model
class Visit < ActiveRecord::Base
attr_accessible :date_visited, :spent, :store_id
belongs_to :
end
Controller
def update_multiple
#visits = Store.find(params[:store_ids])
#visits.each do |visit|
visit.update_attributes(params[:visit])
end
flash[:notice] = "Updated products!"
redirect_to stores_path
end
View
<%= form_for :visit, :url => update_multiple_visits_path, :html => { :method => :put } do |f| %>
<ul>
<% #visits.each do |visit| %>
<%= hidden_field_tag "store_ids[]", visit.id %>
<% end %>
</ul>
<div class="field">
<%= f.label :date_visited %><br />
<%= f.date_select :date_visited %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
<ol id="route">
<% #visits.each do |store| %>
<%= content_tag_for :li, store do %>
<%= "#{store.store} - #{store.address}" %>
<% end %>
<% end %>
</ol>
Most likely, you are missing the attr_accessible :your_model_attributes is this case, :visits_attributes on your activerecord model definition.
Also, your params should look like
{ visits =>
{ id_1 =>
{ :store_id
:attributes_for_visit_1 }
}
{ id_2 =>
{ :store_id
:attributes_for_visit_2 }
}
} # and so on....
# visits_controller.rb
def update_nultiple_visits
#visits = Visits.find(params[:visits].keys).each{|visit|visit.update_attributes!}
end
Add this to your Store model
attr_accessible :visits_attributes
accepts_nested_attributes_for :visits
And I'd suggest changing your controller to this:
def update_multiple
#stores = Store.find(params[:store_ids])
#stores.each do |store|
store.update_attributes(params[:visit])
end
flash[:notice] = "Updated products!"
redirect_to stores_path
end
Helper date_select generate three a select tags (for year, month and day).
You can concatenate its before updating attributes.
For example:
Date.civil(params[:visit][:date_visited(1i)].to_i, params[:visit][:date_visited(2i)].to_i, params[:visit][:date_visited(3i)].to_i)
We have the following code working for a complex rails form with checkboxes. I'm not really happy with the solution we have in place and I was wondering if anyone knows of a more proper way to do this in rails. All the code below is working I just want to know if there is a cleaner approach.
In my Admins controller I want to remove the need to call the following code on each update.
#user.admin.school_admin_roles.destroy_all
params[:roles].each do |school_role|
ids = school_role.split('_')
#user.admin.school_admin_roles.find_or_create_by_school_id_and_school_role_id(ids[0], ids[1])
end if !params[:roles].nil?
So I basically want to be able to call #user.update_attributes(params[:user]) and have rails take care of creating the needed relationships for me. I have that working with AccountRole in the form below. I want to know if there is a way to do the same thing with SchoolRole given I have an extra variable school_id in the join table.
We have the following form for editing a user and assigning roles
Screenshot of form ->
http://i.stack.imgur.com/PJwbf.png
I have the following form where an admin can edit other users and assign account based roles and school based roles via checkboxes. The account based roles were easy to implement. The school based rules are a bit complicated since the join table school_admin_roles has school_id, user_id, role_id fields. We had to implement the school roles part of the form in a rather hackish way. We have the form implemented like this - notice how we hacked together school.id.to_s+'_'+role.id.to_s into the same checkbox on school roles.
In the Admins controller's update function we manually destroy all school_admin roles on each update then loop through the school roles params do a split on the ids on '-' then manually re-create each school based role. I really hate the way we've had to go about this. Could anyone shed some light on a cleaner more rails centric approach to solving this scenario?
The form -
<%= form_for #user, :url => {:controller => 'admins', :action => 'update'} do |f| %>
<%= f.label :username %>
<%= f.text_field :username %>
<%= f.fields_for :admin do |uf| %>
<div class="field">
<%= uf.label :first_name %>
<%= uf.text_field :first_name %>
</div>
<label>Admin Permissions</label>
#account level permissions works fine
<%= hidden_field_tag "#{uf.object_name}[account_role_ids][]" %>
<% AccountRole.find(:all).each do |role| %>
<div class="account_role">
<%= check_box_tag "#{uf.object_name}[account_role_ids][]", role.id, #user.admin.account_roles.include?(role)%>
<%= role.name %>
</div>
<% end %>
#school level permissions a bit of a hack
<%= hidden_field_tag "#{uf.object_name}[school_role_ids][]" %>
<% SchoolRole.find(:all).each_with_index do |role, index| %>
<div class="school_role">
<%= check_box_tag "#{uf.object_name}[school_role_ids][]",role.id, #user.admin.school_roles.include?(role) %>
<%= role.name %>
<span class="advanced_box admin_permissions" <% if #user.admin.school_roles.include?(role) %>style="display:inline"<% end %>>
<div class="content" id="perm_<%= index %>">
<h4><%= role.name %></h4>
<% uf.object.account.schools.each do |school|%>
<div>
<%= check_box_tag "roles[]", school.id.to_s+'_'+role.id.to_s, role.school_admin_roles.where(:admin_id => uf.object.id).collect(&:school_id).include?(school.id)%>
<%= school.name %>
</div>
<% end %>
<%= link_to 'Done', '#', :class => "done" %>
</div>
Advanced
</span>
</div>
<% end %>
</div>
<% end %>
The controller
class AdminsController < ApplicationController
def update
#user = User.find(params[:id])
if #user.update_attributes(params[:user])
# TODO find a way to refactor this
#user.admin.school_admin_roles.destroy_all
params[:roles].each do |school_role|
ids = school_role.split('_')
#user.admin.school_admin_roles.find_or_create_by_school_id_and_school_role_id(ids[0], ids[1])
end if !params[:roles].nil?
#
flash[:notice] = "Successfully updated Admin."
redirect_to admins_path
else
render "edit"
end
end
end
Given the following models
class User < ActiveRecord::Base
has_one :parent
has_one :admin
has_many :scool_admin_roles
has_many :account_admin_roles
end
class AccountAdminRole < ActiveRecord::Base
before_save :set_account_id
belongs_to :admin
belongs_to :account_role
end
class SchoolAdminRole < ActiveRecord::Base
belongs_to :admin
belongs_to :school_role
belongs_to :school
end
class SchoolRole < ActiveRecord::Base
has_many :school_admin_roles
end
class AccountRole < ActiveRecord::Base
has_many :account_admin_role
end
When I face code that I know smells bad, usually it leads me to the design.
In this case, the problem is the database table design.
You are hacking the value passed from a checkbox with a delimiter because the "join" table does more than just join. I believe that the relationship to school belongs_to the SchoolRole and not the SchoolAdminRole. Changing this will create a pattern much like your AccountRole.
Correcting the model design, might be a bit painful now, but it is much cleaner and will be maintainable in the future. You will thank yourself later.
We refactored the code above as follows
In the model we added accepts_nested_attributes_for :school_admin_roles, :reject_if => proc { |attr| attr['school_role_id'].blank? }
and added school_admin_roles_attributes to attr_accessible
class Admin < ActiveRecord::Base
belongs_to :account
belongs_to :user
has_many :school_admin_roles
has_many :school_roles, :through => :school_admin_roles
has_many :account_admin_roles
has_many :account_roles, :through => :account_admin_roles
accepts_nested_attributes_for :account
accepts_nested_attributes_for :school_admin_roles, :reject_if => proc { |attr| attr['school_role_id'].blank? }
attr_accessible :account_role_ids, :email, :first_name, :last_name, :account_id, :user_id, :account_attributes, :school_admin_roles_attributes
default_scope where(:deleted => false)
end
We then built the form as follows
<% index2 = 0 %>
<% SchoolRole.find(:all).each_with_index do |role, index| %>
<div class="school_role">
<%= check_box_tag "school_roles[]",role.id, #user.admin.school_roles.include?(role) %>
<%= role.name %>
<span class="advanced_box admin_permissions" <% if #user.admin.school_roles.include?(role) %>style="display:inline"<% end %>>
div class="content" id="perm_<%= index %>">
<h4><%= role.name %></h4>
<% uf.object.account.schools.each do |school|%>
<div>
<%= check_box_tag "#{uf.object_name}[school_admin_roles_attributes][#{index2}][school_role_id]", role.id, role.school_admin_roles.where(:admin_id => uf.object.id).collect(&:school_id).include?(school.id)%>
<%= school.name %>
<%= hidden_field_tag "#{uf.object_name}[school_admin_roles_attributes][#{index2}][school_id]", school.id %>
</div>
<% index2 += 1 %>
<% end %>
<%= link_to 'Done', '#', :class => "done" %>
</div>
Advanced
</span>
</div>
<% end %>
</div>
<% end %>
Which then enabled us to refactor the controller without splitting the ids but we still have to call destroy all each time which I can live with.
def update
#user = User.find(params[:id])
#user.admin.school_admin_roles.destroy_all
if #user.update_attributes(params[:user])
flash[:notice] = "Successfully updated Admin."
redirect_to admins_path
else
render "edit"
end
end