Reputation: 776
I have a nested form for a user, portfolios, and photos. Basically a user can create a portfolio by uploading photos in ANOTHER FORM. However, then I want to give them a chance to create a new portfolio, by selecting some photos from the current portfolio they are viewing, and have the method resubmit
in PortfolioController
create a new portfolio for them. The models are:
class User < ActiveRecord::Base
has_many: portfolios
end
class Portfolio < ActiveRecord::Base
has_many: photos
belongs_to: user
end
class Photo < ActiveRecord::Base
belongs_to: portfolio
attr_accessor :move
end
The controller is:
class PortfolioController < ApplicationController
//... some generic code
def resubmit
// This is where I need help
end
def display
@userPortfolio = Portfolio.where(:id => params[:uid]).first
end
end
and the view is:
<%= simple_form_for @userPortfolio, :url => {:action => resubmit} do |f|%>
<%= f.label current_user.name %>
<% @images = @userPortfolio.photos %>
<% @images.each do |anImage| %>
<%= f.fields_for :anImage do |ff| %>
<%= ff.checkbox :move, :id => "move_#{anImage.id}" %><%=ff.label :move, "Move image #{anImage.name} to new portfolio?" %>
<% end %>
<% end %>
<%= f.submit "Create new portfolio" %>
<% end %>
Basically once the user hits submit I want the method resubmit
to create a new portfolio with a collection of new photos that are the same as the photos selected. That is, I want to create 1 new record of portfolio
and several new records photo
, as many as the user has selected, based on the properties of the photos the user selected, so I need to access the records that represent the selected photos. How do I access all the photos the user has selected? I can't simply create a finite set of checkbox controllers on the form since the number displayed depends on the number of photos in the current portfolio.
Upvotes: 0
Views: 96
Reputation: 776
Okay, so it seems what I was trying to do was fairly simple after all. No need for nested_form, the simple_form does just as well. But I'm sure nested_form (as Tory SK suggested) does the trick as well. The major point was adding attr_accessor:
to the code.
Basically the code is as follows:
class User < ActiveRecord::Base
has_many: portfolios
end
class Portfolio < ActiveRecord::Base
has_many: photos
belongs_to: user
attr_accessor: photos_attributes // This is an important piece of code
end
class Photo < ActiveRecord::Base
belongs_to: portfolio
attr_accessor :move
end
Then I simply changed the form as follows (notice the additional :pid => params[:pid]
so that I can figure out in resubmit
which portfolio I need to access IF I need to access it):
<%= simple_form_for @userPortfolio, :url => {:action => "resubmit", :pid => params[:pid]} do |f|%>
<%= f.label current_user.name %>
<% @images = @userPortfolio.photos
i = 0
%>
<%= f.fields_for :images do |ff| %>
<% anImage = @images[i] %>
<%= ff.checkbox :move, :id => "move_#{anImage.id}" %><%=ff.label :move, "Move image #{anImage.name} to new portfolio?" %>
<% i = i+1%>
<% end %>
<%= f.submit "Create new portfolio" %>
<% end %>
And when you hit submit and send the form to resubmit
, the params
dictionary contains the following:
{"utf8"=>"✓",
... more parameters
"portfolio"=>{"photos_attributes"=>{"0"=>{"move"=>"0",
"id"=>"1"},
"1"=>{"move"=>"0",
"id"=>"2"},
...
"4"=>{"move"=>"0",
"id"=>"5"}}},
"commit"=>"Submit Job",
"pid"=>"1"}
Now I can just iterate through the checkboxes and compare them to all the photos that belong to the current portfolio in resubmit
def resubmit
@myImages = Portfolio.where(:id => params[:pid]).photos
// iterate through each image and use a counter to access
// the dictionary elements to see if they were checked
end
Upvotes: 0
Reputation: 1289
Use the gem nested_form or cocoon to make the elements dynamic. On the backend use the selected items to create entries for the new portfolio.
Upvotes: 1