Querying multiple linked classes in Rails - ruby-on-rails

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 %>

Related

has_many through access join table attribute in form

I have the following models:
class RandomExam < ActiveRecord::Base
has_many :random_exam_sections
has_many :sections, :through => :random_exam_sections
end
class Section < ActiveRecord::Base
has_many :random_exam_sections
has_many :random_exams, :through => :random_exam_sections
class RandomExamSection < ActiveRecord::Base
belongs_to :random_exam
belongs_to :section
end
The idea is to have certain configurations to create random exams, so this tables help to select which sections do you need and then also select the number of questions per section, here are the attributes of each table:
RandomExam: name(string), created_at(datetime), updated_at(datetime)
Section: name(string), created_at(datetime), updated_at(datetime)
RandomExamSection: random_exam_id(integer), section_id(integer), questions_number(integer)
As you can see the number of questions per section attribute is inside the RandomExamSections table and I want to access it in a form that is displayed from the RandomExam controller, here is my form:
<%= form_for (#random_exam) do |f| %>
<div class="row">
<div class="input-field col s12">
<%= f.label :name, 'Name' %>
<%= f.text_field :name, placeholder: 'Enter the name of the configuration' %>
</div>
</div>
<% #sections.each do |section| %>
<div class="row <%= dom_id(section) %>">
<div class="col s4">
<%= check_box_tag 'random_exam[section_ids][]', section.id,
#random_exam.section_ids.include?(section.id), id: dom_id(section), class: "section-checkbox #{dom_id(section)}" %>
<%= label_tag dom_id(section), (raw sanitize section.name, tags: %w(h2 p strong em a br b i small u ul ol li blockquote), attributes: %w(id class href)),
class: "name #{dom_id(section)}" %>
</div class="col s4">
<div>
<%= text_field_tag "random_exam[random_questions_numbers][#{section.id}][]", nil,
:placeholder => 'Enter the number of questions' %>
</div>
</div>
<% end %>
<div class="form-group">
<%= f.submit class: "btn waves-effect waves-light green" %>
</div>
<% end %>
My controller:
def create
#random_exam = RandomExam.new(random_exam_params)
if #random_exam.save
assign_random_questions_number
flash[:success] = 'Random configuration created successfully'
redirect_to #random_exam
else
flash.now[:danger] = #random_exam.errors.full_messages.to_sentence
render 'new'
end
def assign_random_questions_number
if params[:random_exam][:'random_questions_numbers'] == nil
return
end
params[:random_exam][:'section_ids'].each do |key, value|
record = RandomExamSection.search_ids(#random_exam.id, key)
record.each do |random_exam_section_record|
number_of_questions = params[:random_exam][:'random_questions_numbers'][key].first.to_i
random_exam_section_record.update(questions_number: number_of_questions)
end
end
end
I'm getting a TypeError: TypeError: nil is not a symbol nor a string when I update the record in the method assign_random_questions_number
This error even appears when I run this on the console
random = RandomExamSection.first
random.update(questions_number: 10)
Or when I run:
random = RandomExamSection.first
random.questions_number = 10
random.save
EDIT
I ended up deleting the association in RandomExamSection and recreating it inside 'assign_random_questions_number' with the questions_number
Thanks.
If you use nested_attributes you can do something like this:
#form
<h4>Selected exams</h4>
<%= f.fields_for :random_exam_sections do |b| %>
<%= b.hidden_field :section_id %>
<%= b.label :selected, b.object.section.name %>
<%= b.check_box :selected, { checked: !b.object.id.blank? } %>
<br>
<%= b.label :question_numbers %>
<%= b.text_field :questions_number %>
<% end %>
#RandomExamModel
class RandomExam < ApplicationRecord
has_many :random_exam_sections, inverse_of: :random_exam
has_many :sections, :through => :random_exam_sections
accepts_nested_attributes_for :random_exam_sections, reject_if: :is_not_selected
private
def is_not_selected(attr)
attr["selected"] == '0'
end
end
# RandomExam
class RandomExamSection < ApplicationRecord
belongs_to :random_exam
belongs_to :section
attr_accessor :selected
end
# Controller
# GET /random_exams/new
def new
#random_exam = RandomExam.new
#random_exam.random_exam_sections.build(Section.all.map{|s| {section_id: s.id}})
end
The idea basically is
- Build on controller the random_exam_sections to be selected
- Write a form that allows to you 'select' one option and assign the number
- Then, validate if the random_exam_section of a sections was selected (this why i made that `attr_accessor :selected`, i need a place to write if user select the exam_section)
- If was selected, save.
The trick here is build on the controller, then select on the view and validate the selected on the model. Here i made an example if you need help: https://github.com/afromankenobi/nested_attr_demo
To add sections when the random_exam_sections is already created you should probably use javascript. Maybe this railscasts can help you http://railscasts.com/episodes/196-nested-model-form-part-1

Weird Routing Behavior in Rails

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)

Undefined Method Error When Rendering Partial

So, I entirely understand why one would normally receive an undefined method error, however, I am unsure why it is happening this particular time.
I have a partial:
submissions/_submission.html.erb
<div class="pure-u-1-2 rounded">
<%= link_to submission do %>
<div class="rounded" style="background-color: #B81324; color: #E6E6E6; margin: 10px; padding:5px;">
<div class="clear">Project: <%= submission.project.title %></div>
<div class="clear">Submitted By: <%= submission.submitter.username %></div>
<div class="clear">Amount: $<%= submission.price %></div>
<div class="clear">Description: <%= submission.description %></div>
</div>
<% end %>
</div>
This partial is used twice in my dashboard/index.html.erb
Once to render a collection of received submissions and again to render a collection of sent submissions:
dashboards/index.html.erb
<% if #received_submissions.length > 0 %>
<div class="pure-u-1" id="projects"><h3 class="red">Final Tracks Received (<%= #received_submissions.length %>)</h3>
<%= render :partial => :submission, :collection => #received_submissions %>
</div>
<% end %>
<% if #sent_submissions.length != 0 %>
<div class="pure-u-1" id="projects"><h3 class="red">Final Tracks Sent (<%= #sent_submissions.length %>)</h3>
<%= render :partial => :submission, :collection => #sent_submissions %>
</div>
<% end %>
However, rendering the received submissions works without ailment, and rendering the sent submissions errors out with:
undefined method `submissions' for #<PlayerProject:0x000001052730e8>
Here is the dashboards_controller also, just in case:
class DashboardsController < ApplicationController
before_filter :authenticate_user!
def index
#compact = current_user.projects.where.not(status: ['Deleted','Closed']).order("id desc")
#projects = current_user.projects.where.not(status: ['Deleted','Closed']).order("id desc")
#received_messages = current_user.received_messages
#received_submissions = current_user.projects.collect{|p| p.submissions }.flatten
#player = current_user.player_projects.collect{|pp| pp.project}
#sent_submissions = current_user.player_projects.collect{|ps| ps.submissions }.flatten
end
end
models/player_project.rb'
class PlayerProject < ActiveRecord::Base
belongs_to :project
belongs_to :player, :class_name => "User"
end
models/submission.rb
class Submission < ActiveRecord::Base
belongs_to :submitter, :class_name => "User"
belongs_to :recipient, :class_name => "User"
belongs_to :project
validates :amount_in_cents, :presence => true, length: { minimum: 2, :message => " must be more than $0" }
validates :description, :presence => { :message => " cannot be blank" }
validates :final_track_url, :presence => { :message => " Required" }
def price
sprintf "%.2f", (self.amount_in_cents.to_f/100.0)
end
def price=(val)
self.amount_in_cents = (val.to_f*100.0).to_i
end
def paid?
!!self.paypal_confirmation
end
end
I think your error will be model-level:
undefined method `submissions' for #<PlayerProject:0x000001052730e8>
Association
This typically suggests you don't have a particular association set up (I.E you're calling #model.x when x is not defined):
#sent_submissions = current_user.player_projects.collect{|ps| ps.submissions }.flatten
Although your player_projects is defined, I think your submissions attribute / association does not exist. Besides, you can use the pluck method to help this: current_user.player_projects.pluck(:submissions)
Firstly, do you have the submissions attribute in your table?
Secondly, if you don't, what are you trying to achieve with it? You don't typically have a plural column in your table (denotes multiple data stores). I would use an association on a join-model
Try this
<%= render "submission", :collection => #sent_submissions %>

Adding empty record for nested attribute in rails

I'm working in Rails 4/Ruby 2.0.0. I have a two models - Articles and Graphics. Articles has_many Graphics. So, in my code I am trying to add an empty record to the graphics collection on the article so that in the form, there will be an empty set of fields to let a new record be added. I cannot figure out why the fields do not show up on the form though.
I've tried multiple methods of building the graphics collection but none seem to do the trick. Surely I must be missing something insanely small.
Article.rb
class Article < ActiveRecord::Base
has_many :graphics, :dependent => :destroy, :foreign_key => 'article_id'
accepts_nested_attributes_for :graphics,
:allow_destroy => true,
:reject_if => :all_blank
end
Graphic.rb
class Graphic < ActiveRecord::Base
belongs_to :article
validates_presence_of :path, :caption
end
_form.html.erb
...
<% f.fields_for :graphics do |g| %>
<div class="clear clearfix pad-b-20">
<div class="w-1-2 left f-left">
<div class="field">
<%= g.label :path %><br>
<%= g.text_field :path %>
</div>
</div>
<div class="w-1-2 left f-left">
<div class="field">
<%= g.label :caption %><br>
<%= g.text_field :caption %>
</div>
</div>
</div>
<% end %>
...
Building it in a form helper method
articles/_form.html.erb
<%= form_for(setup_article(#article)) do |f| %>
form_helper.rb
module FormHelper
def setup_article(article)
article.graphics.build
article
end
end
Using an ActiveRecord callback
Article.rb
...
after_initialize :build_graphics
private
def build_graphics
self.graphics.build
end
Building it in the controller
ArticleController.rb
...
def new
#article = Article.new
#article.graphics.build
end
...
The problem is that both for form_for and for fields_for you need to use <%=, because they render the contents of the form.
So, to solve your problem, you need to write
...
<%= f.fields_for :graphics do |g| %>
Your content
<% end %>
...

Rails has_many checkboxes with extra attribtues

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

Resources