Absolutely stuck trying to create nested association in rails form with has_many through -
i posted earlier question , advised read lots of relevant info. have read , tried implementing 30 different solutions. none of have worked me.
here's i've got.
i have miniatures model. have manufacturers model. miniatures have many manufacturers through productions model.
the associations seem set correctly can show them in views , create them via console. have problem in letting miniatures new , edit views create , update productions table.
in console command @miniature.productions.create(manufacturer_id: 1) works, leads me believe should able same in form.
i think problem in miniatures controller , create function. have tried out ton of other peoples solutions there , none have done trick. possible field_for stuff in form wrong seems less fiddly.
i've been stuck on days , while there other things work on, if association isn't possible i'd need rethink entire application.
the form creates line in productions table doesn't include important manufacturer_id.
any appreciated.
my new miniature form
<% provide(:title, 'add miniature') %> <h1>add miniature</h1> <div class="row"> <div class="span6 offset3"> <%= form_for(@miniature) |f| %> <%= render 'shared/error_messages', object: f.object %> <%= f.label :name %> <%= f.text_field :name %> <%= f.fields_for :production |production_fields| %> <%= production_fields.label :manufacturer_id, "manufacturer" %> <%= production_fields.select :manufacturer_id, options_from_collection_for_select(manufacturer.all, :id, :name) %> <% end %> <%= f.label :release_date %> <%= f.date_select :release_date, :start_year => date.current.year, :end_year => 1970, :include_blank => true %> <%= f.submit "add miniature", class: "btn btn-large btn-primary" %> <% end %> </div> </div> miniatures controller
class miniaturescontroller < applicationcontroller before_action :signed_in_user, only: [:new, :create, :edit, :update] before_action :admin_user, only: :destroy def productions @production = @miniature.productions end def show @miniature = miniature.find(params[:id]) end def new @miniature = miniature.new end def edit @miniature = miniature.find(params[:id]) end def update @miniature = miniature.find(params[:id]) if @miniature.update_attributes(miniature_params) flash[:success] = "miniature updated" redirect_to @miniature else render 'edit' end end def index @miniatures = miniature.paginate(page: params[:page]) end def create @miniature = miniature.new(miniature_params) if @miniature.save @production = @miniature.productions.create redirect_to @miniature else render 'new' end end def destroy miniature.find(params[:id]).destroy flash[:success] = "miniature destroyed." redirect_to miniatures_url end private def miniature_params params.require(:miniature).permit(:name, :release_date, :material, :scale, :production, :production_attributes) end def admin_user redirect_to(root_url) unless current_user.admin? end def signed_in_user unless signed_in? store_location redirect_to signin_url, notice: "please sign in." end end end miniature model
class miniature < activerecord::base has_many :productions, dependent: :destroy has_many :manufacturers, :through => :productions accepts_nested_attributes_for :productions validates :name, presence: true, length: { maximum: 50 } validates :material, presence: true validates :scale, presence: true validates_date :release_date, :allow_blank => true def name=(s) super s.titleize end end production model
class production < activerecord::base belongs_to :miniature belongs_to :manufacturer end manufacturer model
class manufacturer < activerecord::base has_many :productions has_many :miniatures, :through => :productions validates :name, presence: true, length: { maximum: 50 } accepts_nested_attributes_for :productions end
instead of calling:
@production = @miniature.productions.create try rails' "build" method:
def new @miniature = miniature.new(miniature_params) @miniature.productions.build end def create @miniature = miniature.new(miniature_params) if @miniature.save redirect_to @miniature else render 'new' end end using build method uses activerecord's autosave association functionality.
see http://api.rubyonrails.org/classes/activerecord/autosaveassociation.html
you need update params method, e.g.
def miniature_params params.require(:miniature).permit(:name, :release_date, :material, :scale, productions_attributes: [:manufacturer_id]) end also fields_for should plural (i think)...
<%= f.fields_for :productions |production_fields| %>
Comments
Post a Comment