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.
--
You received this message because you are subscribed to the Google Groups
"Ruby on Rails: Talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to
rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
To post to this group, send email to
rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
To view this discussion on the web visit
https://groups.google.com/d/msg/rubyonrails-talk/-/NuK71fNT6hkJ.
For more options, visit https://groups.google.com/groups/opt_out.
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.
--
You received this message because you are subscribed to the Google Groups
"Ruby on Rails: Talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to
rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
To post to this group, send email to
rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
To view this discussion on the web visit
https://groups.google.com/d/msg/rubyonrails-talk/-/x0Aey747JSkJ.
For more options, visit https://groups.google.com/groups/opt_out.
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> 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? } >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> 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(''table'').find("tr.entry_header").hide(); > $(link).closest(".fields").hide(); > } > > function add_fields(link, association_id, content) { > var new_id = new Date().getTime(); > var regexp = new RegExp(association_id, "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) > new_object = f.object.send(association).klass.new > id = new_object.object_id > timesheet.create_activity_days(new_object) > > fields = f.fields_for(association, new_object, child_index: id) do > |builder| > render(association.to_s.singularize + "_fields", f: builder) > end > > > 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. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To unsubscribe from this group and stop receiving emails from it, send an email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To view this discussion on the web visit https://groups.google.com/d/msg/rubyonrails-talk/-/SPqrx4OMJIsJ. For more options, visit https://groups.google.com/groups/opt_out.