Bob Boyken wrote:
> I have an application I am working on which deals with projects and
> subcontractors. There can be several subs on each project and each sub
> can work on several projects. I have my join table set up and
> has_and_belongs_to_many in both models. If I manually put data in the
> join table, this works in my show view:
>
> <% for subcontractor in @project.subcontractors %>
> <%= subcontractor.name %><br />
> <% end %>
>
> I get the correct list of subcontractors belonging to this project.
>
> My question is this: How do I get data into the join table? If I were
> doing this in PHP, I would have a button that said "Add a
Subcontractor"
> that would pop up a window with a dropdown where the user would select a
> sub. I would then refresh the page and then refresh the page and the new
> sub would appear in the list.
>
> What is the "Rails Way" to do the same thing? I want the user to
select
> a sub from a dropdown, but I have no idea how to implement this. Let me
> phrase that better, I know how to use collection_select for a
"normal"
> lookup table situation where I have has_many and belongs_to. It''s
this
> habtm situation that has me stymied. What needs to go in the controller
> and what needs to go in the view for this to work?
You can do the same thing you''d do in PHP in Rails.
The popup would be called from the main edit_project page with:
<%= link_to ''Add a subcontractor'',
{:action => ''add_subcontractor'', :id =>
@project.id} %>,
:popup => [''new_window'', ''height=300,
width=600''] %>
The RHTML for the pop-up would be:
<%= form_tag %>
<%= select_tag ''subcontractor_id'',
options_for_select([[''Select a subcontractor to add'',0]]
+
Subcontractor.find(:all).map {|s| [s.name,s.id]}),
:onchange => ''this.form.submit(); window.close()''
%>
<%= end_form_tag %>
The controller code for the pop-up would be:
def add_subcontractor
if request.post?
project = Project.find(params[:id])
sid = params[:subcontractor_id].to_i
project.subcontractors << Subcontractor.find(sid) if sid != 0
render :nothing => true
end
end
You could even get away without the need to refresh the edit_project
window by adding to the select on_change
window.opener.add_subcontractor(value)
and having this function insert the subcontractor into the HTML list
from a JavaScript subcontractor id-to-name array or hash.
However there would be no check that there was no error while
adding the subcontractor in the controller unless you delayed
this callback to the parent window until after the post returned
successfully.
--
We develop, watch us RoR, in numbers too big to ignore.