How is it possible to use a callback and which one to avoid the
destroying
of the last association.
For example, there are 3 following models:
#timesheet.rb
class Timesheet < ActiveRecord::Base
has_many :activities, dependent: :destroy
has_many :time_entries, through: :activities
accepts_nested_attributes_for :activities, allow_destroy: true
end
#activity.rb
class Activity < ActiveRecord::Base
has_many :time_entries, order: :workdate, dependent: :destroy
accepts_nested_attributes_for :time_entries, allow_destroy: true,
reject_if: proc { |a| a[:worktime].blank? }
end
#time_entry.rb
class TimeEntry < ActiveRecord::Base
belongs_to :activity
validates :worktime, presence: true, inclusion: { in: [0.5, 1] }
end
Every timesheet is created for 7 days (tile_entries) for one activity in
the the same form. To delete I use the technic with jQuery explained at
Railscats:
#add_remove_fields.js
function remove_fields(link) {
$(link).prev("input[type=hidden]").val("1");
$(link).closest(".fields").hide();
}
function add_fields(link, association, content) {
var new_id = new Date().getTime();
var regexp = new RegExp("new_" + association, "g");
$(link).parent().before(content.replace(regexp, new_id));
}
#application_helper.rb
def link_to_remove_fields(name, f)
f.hidden_field(:_destroy) + link_to_function(name,
"remove_fields(this)")
end
def link_to_add_fields(name, f, association, timesheet)
...
end
I tried several ways with after_destroy hook, - it didn't work.
Any idea ? Thanks and regards.
on 2013-03-14 20:14
on 2013-03-19 15:31
So still no idea how to avoid the destroy of the last association. I do
all
the processing in the 'update ' action of TimesheetsController. I tried
with 'after_update' hook in the Timsheet model as follows:
#timesheet.rb
class Timesheet < ActiveRecord::Base
accepts_nested_attributes_for :activities, allow_destroy: true
after_update :check_an_activity_present
private
def check_an_activity_present
raise "You should have at least ONE activity present" if
activities.empty?
end
end
An I put the update_attributes in the begin/rescue block in the
controller:
#timesheets_controller.rb
class TimesheetsController < ApplicationController
def update
begin
@timesheet = current_user.timesheets.find(params[:id])
if @timesheet.update_attributes(params[:timesheet])
flash[:success] = 'Timesheet updated sucessfully'
redirect_to @timesheet
else
load_entries
render 'edit'
end
rescue Exception => e
flash.now[:error] = e.message
@entries = @timesheet.time_entries
render 'edit'
end
private
def load_entries
@entries = @timesheet.build_and_sort_time_entries
end
end
end
The problem is that the activity with corresponding time entries
collection
is not destroyed even if I added a new activity with corresponding time
entries. So after the update executed, I have 2 activities saved with
corresponding time entries instad of having just the ONLY one, entered
just
after the destroying the previous one. Any idea? Thank you.
on 2013-03-19 21:52
Finally, after_update callback works as needed, te problem was in the new fields_for generation. The below is the correct and updated version: #timesheet.rb > reject_if: proc { |a| a[:worktime].blank? } > validate :one_time_entry_present private def one_time_entry_present errors[:base] << "At least one entry should be entered" if time_entries.empty? end > Railscats: > var regexp = new RegExp(association_id, "g"); > def link_to_add_fields(name, f, association, timesheet) > link_to_function(name, "add_fields(this, \"#{id}\", > \"#{escape_javascript(fields)}\")") > end > #timesheets_controller.rb def update begin @timesheet = current_user.timesheets.find(params[:id]) if @timesheet.update_attributes(params[:timesheet]) flash[:success] = 'Timesheet updated sucessfully' redirect_to @timesheet else load_entries render 'edit' end rescue Exception => e flash[:error] = e.message redirect_to edit_timesheet_path(@timesheet) end end Hope this helps.
Please log in before posting. Registration is free and takes only a minute.
Existing account
(Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
Log in with Google account | Log in with Yahoo account
No account? Register here.