require 'tempfile' require 'console_update/named_scope' require 'console_update/filter' require 'console_update/version' module ConsoleUpdate class <10 # Url.console_update records # Url.console_update records, :only=>%w{column1} # Url.console_update records, :except=>%w{column1} def console_update(records, options={}) begin editable_attributes_array = records.map {|e| e.console_editable_attributes(options) } editable_string = filter.hashes_to_string(editable_attributes_array) new_attributes_array = editor_update(editable_string) records.each do |record| if (record_attributes = new_attributes_array.detect {|e| e['id'] == record.id }) record.update_console_attributes(record_attributes) end end rescue ConsoleUpdate::Filter::AbstractMethodError puts "Undefined filter method for #{ConsoleUpdate::filter} filter" rescue StandardError=>e puts "Some record(s) didn't update because of this error: #{e}" ensure #this attribute should only last duration of method reset_editable_attribute_names end end def filter #:nodoc: @filter ||= ConsoleUpdate::Filter.new(ConsoleUpdate.filter) end # Console updates a record given an id. def find_and_console_update(id, options={}) console_update([find(id)], options) end # :stopdoc: def editor_update(string) tmpfile = Tempfile.new('console_update') File.open(tmpfile.path, 'w+') {|f| f.write(string)} system(console_editor, tmpfile.path) updated_string = File.read(tmpfile.path) filter.string_to_hashes(updated_string) end def reset_editable_attribute_names; @editable_attribute_names = nil ; end def editable_attribute_names(options={}) unless @editable_attribute_names @editable_attribute_names = if options[:only] options[:only] elsif options[:except] default_editable_attributes - options[:except] else default_editable_attributes end end @editable_attribute_names end # :startdoc: end module InstanceMethods # Console updates the object. def console_update(options={}) self.class.console_update([self], options) end # :stopdoc: def update_console_attributes(new_attributes) # delete if value is the same or is an attribute that isn't supposed to be edited new_attributes.delete_if {|k,v| attributes[k] == v || !self.class.editable_attribute_names.include?(k) } new_attributes.each do |k, v| send("#{k}=", v) end save end def get_console_attributes(attribute_names) attribute_names.inject({}) {|h,e| h[e] = attributes.has_key?(e) ? attributes[e] : send(e) h } end def console_editable_attributes(options) fresh_attributes = get_console_attributes(self.class.editable_attribute_names(options)) fresh_attributes['id'] ||= self.id fresh_attributes end #:startdoc: end end ActiveRecord::Base.send :include, ConsoleUpdate if defined?(ActiveRecord::Base)