link_to_remove_association is not removing?

AnthonyGalli.com picture AnthonyGalli.com · Jun 21, 2015 · Viewed 8.1k times · Source

How can we fix the nested_attribute: _result_fields.html.erb so that when a user clicks "Delete" that it actually deletes it? Whereas now clicking it does nothing.

<%= f.text_field :result_value, class: 'form-control', placeholder: 'Enter Result' %>
<%= f.date_select :date_value, :order => [:month, :day, :year], :with_css_classes => true, :class => "date-select" %>
<%= f.check_box :bad %>
<%= link_to_remove_association f do %>
  Delete
<% end %>

stats has_many results

stats/_form

<div id="results">
  <%= f.fields_for :results do |result| %>
  <%= render 'result_fields', :f => result %>
  <% end %>
</div>

  <span class="label label-primary">
    <%= link_to_add_association f, :results do %>
    <span class="glyphicon glyphicon-plus"></span> Result
    <% end %>
  </span>

In stats_controller I have this as a params: results_attributes: [:id, :result_value, :date_value, :bad, :_destroy]

The models:

class Stat < ActiveRecord::Base
  has_many :results
  accepts_nested_attributes_for :results, :reject_if => :all_blank, :allow_destroy => true
end

class Result < ActiveRecord::Base
  belongs_to :stat
end

I'm using the cocoon gem.

Please let me know if you need further code or explanation. Thank you!

BY REQUEST

class StatsController < ApplicationController
  before_action :set_stat, only: [:show, :edit, :update, :destroy, :like]
  before_action :logged_in_user, only: [:create, :destroy]
  before_action :correct_user, only: [:edit, :update, :destroy]

  def index
    if params[:tag]
      @stats = Stat.tagged_with(params[:tag])
    else
      @stats = Stat.joins(:results).all
      @averaged_stats = current_user.stats.averaged
      @instance_stats = current_user.stats.instance
    end
  end

  def show
    @stat = Stat.find(params[:id])
    @commentable = @stat
    @comments = @commentable.comments
    @comment = Comment.new
    @notable = @stat
    @notes = @notable.notes
    @note = Note.new
    @correct_user = current_user.stats.find_by(id: params[:id])
  end

  def new
    @stat = current_user.stats.build 
  end

  def edit
  end

  def create
    @stat = current_user.stats.build(stat_params)
    if (params[:commit] == 'conceal')
      @stat.conceal = true
      @stat.save
      redirect_to @stat, notice: 'Stat was successfully created'
    elsif
      @stat.save
      track_activity @stat
      redirect_to @stat, notice: 'Stat was successfully created'
    else
      flash.now[:danger] = 'Required Fields: "Averaged or Instance", "Enter Action", "Enter Metric", and "+ Result"'
      render 'new'
    end
  end

  def update
    if @stat.update(stat_params)
      redirect_to stats_url, notice: 'Goal was successfully updated'
    else
      render action: 'edit'
  end
end

  def destroy
    @stat.destroy
    @result.destroy
    redirect_to stats_url
  end

  def like
    @stat = Stat.find(params[:id])
    @stat_like = current_user.stat_likes.build(stat: @stat)
    if @stat_like.save
      @stat.increment!(:likes)
      flash[:success] = 'Thanks for liking!'
    else
      flash[:error] = 'Two many likes'
    end  
      redirect_to(:back)
  end

  private
    def set_stat
      @stat = Stat.find(params[:id])
    end

    def correct_user
      @stat = current_user.stats.find_by(id: params[:id])
      redirect_to root_url, notice: "Not authorized to edit this stat" if @stat.nil?
    end

    def stat_params
      params.require(:stat).permit(:categories, :like, :action, :metric, :date, :comment, :private_submit, :tag_list, results_attributes: [:id, :result_value, :date_value, :bad, :_destroy])
    end
end

stat.js

$( document ).ready(function() {
  $('.date-format-switcher').click(function(event){
    event;
    if ($(this).attr('id') == 'stat_categories_instance') {
      $('.day').show();
     } else if ($(this).attr('id') == 'stat_categories_averaged') {
        $('.day').hide();
    }
})
  $('.add-form-padding').on('cocoon:after-insert', function(e, insertedItem) {
    if($('#stat_categories_instance').is(':checked')) {
      $('.day').show();
    } else {
        $('.day').hide();
    }
})
});

Answer

nathanvda picture nathanvda · Jun 22, 2015

If the link_to_add_association works, the javascript is loaded correctly.

Still a bit confused about what is not working. If clicking the link_to_remove_association does not remove anything visibly from the page, you are missing the correct wrapper-class. By default it should be .nested-fields, but this can be overruled by specifying it explicitly (as documented ).

But if the items are visually removed, and you think it should be sent to the server immediately, then you misunderstand how cocoon works: you edit a form, which is only saved (sent to the server) when you submit the form. So the link_to_remove_association only visible removes the nested-child, and edits the contents of the form (sets the _destroy flag), so when saving/submitting the form, the nested child will be deleted.