Skip to content

Instantly share code, notes, and snippets.

@jeromelefeuvre
Created June 21, 2012 12:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jeromelefeuvre/2965506 to your computer and use it in GitHub Desktop.
Save jeromelefeuvre/2965506 to your computer and use it in GitHub Desktop.
Permit to export object with relation as yaml
module Extensions
module HasYamlExport
extend ActiveSupport::Concern
# include class methods here
module ClassMethods
# Get options for relations
# :all => true # Add fields
# :only => [:field1, :field2] # Add only fields here
# :except => [:field1, :field2] # Do not display fields here
# :include => {:relation1 => [:all => true, :only => [], :except => [], :include => ...]} # Permit to add relations with same schema as top
def nested_attributes
begin
@nested_attributes ||= eval("#{self}::NESTED_ATTRIBUTES")
rescue Exception => e
{}
end
end
# Get options for the model
def yaml_attributes
begin
@yaml_attributes ||= eval("#{self}::YAML_ATTRIBUTES")
rescue Exception => e
@yaml_attributes ||= {:all => true}
end
end
end
# include Instance methods
module InstanceMethods
# Create the hash according options
def to_hash_export
yaml = {
self.class.to_s.singularize.underscore => to_yaml_attributes(self, self.class.yaml_attributes)
}
self.class.nested_attributes.select{|nested_attribute, options| self.send(nested_attribute).present?}.each do |nested_attribute, options|
next if (object = self.send(nested_attribute)).blank?
next if (options = i18n_attributes(nested_attribute, options)).blank?
# Next if nested attributes return no result
next if (result = records_of(object, options)).blank?
yaml[self.class.to_s.singularize.underscore].merge!({
"%s_attributes" % nested_attribute => result
})
end
yaml
end
# Transform the hash to yaml export
def to_yaml_export
to_hash_export.to_yaml
end
# Collection of keys filtered without rejected keys
def to_yaml_keys object, options
keys = []
keys = object.attributes.collect{|key, value| key} if options[:all].present? or options[:only].present? or options[:except].present?
keys = keys.select{|key| options[:only].include?(key.to_sym)} if options[:only].present?
keys = keys.reject{|key, value| to_yaml_rejected_keys(keys, object, options).include?(key.to_sym)}
# Remove attachmnents attributes fields and add attachment_url
object.class.attachment_definition_keys.each do |attachment|
if keys.include?(attachment) or keys.include?("%s_file_name" % attachment)
keys << "%s_remote_url" % [attachment]
keys.reject!{|key, value| attachment_attributes(attachment).include?(key)}
end
end
if (methods = options[:methods]).present?
keys += methods.collect{|method| method.to_s}
end
keys.sort
end
# Set rejected keys
def to_yaml_rejected_keys keys, object, options
rejected_keys = [:id, :created_at, :updated_at, :deleted_at]
rejected_keys += options[:except] if options[:except].present?
rejected_keys
end
# Return attributes of object filtered without rejected keys
def to_yaml_attributes object, options
attributes = {}
to_yaml_keys(object, options).each{|key| attributes.merge!({ key => object.send(key) }) }
if options[:include].present?
options[:include].each do |key, values|
next if (object = object.send(key)).blank?
next if (sub_options = i18n_attributes(key, values)).blank?
# Next if nested attributes return no result
next if (result = records_of(object, sub_options)).blank?
attributes.merge!({
"%s_attributes" % key => result}
)
end
end
attributes
end
private
####################################################################################
# Seed export methods
####################################################################################
# Set fields using when attachment field
def attachment_attributes attachment
%w(content_type file_name file_size updated_at).collect{|key| "%s_%s" % [attachment, key]}
end
# Update options with i18n attributes according nested attributes model
def i18n_attributes nested_attribute, options
if nested_attribute.to_s.singularize.classify.constantize.respond_to? :translated_attribute_names
translated_attributes = nested_attribute.to_s.classify.constantize.translated_attribute_names
translated_attributes.each do |translated_attribute|
options[:methods] ||= []
available_locales.each do |locale|
options[:methods] << "%s_%s" % [translated_attribute, locale]
end
options[:only].delete(translated_attribute)
end
end
options
end
def available_locales
self.locales || I18n.available_locales
end
def records_of object, options
if object.is_a?(Array)
object.collect{|object| to_yaml_attributes(object, options) }
else
to_yaml_attributes(object, options)
end
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment