Skip to content

Instantly share code, notes, and snippets.

@froger
Last active October 6, 2016 17:53
Show Gist options
  • Save froger/8c9b22ffbaff991d9f6c3430617ab47d to your computer and use it in GitHub Desktop.
Save froger/8c9b22ffbaff991d9f6c3430617ab47d to your computer and use it in GitHub Desktop.
Reflections methods on ActiveRecord relations, for serialization
###
# Rails : 5.0.0
# Ruby : 2.3.0
#
# Reflections methods on ActiveRecord relations, for serialization
# purpose, for example.
#
# I used this to have some Hypermedia document when responding in JSON,
# with this informations, I could easily guess the _embedded links
# of my resources.
##
# Give an array of informations about each belongs_to associations
# of the ActiveRecord given.
#
# If the class given isn't an ActiveRecord, will return an empty array.
#
#
# Example of return
# ```
# class Contact < ActiveRecord::Base
# belongs_to :user
# end
#
#
# > relation_infos(Contact, :belongs_to)
# [
# {
# association_name: :user,
# association_klass_name: "User",
# association_klass: User,
# foreign_key: "user_id"
# }
# ]
# ```
def relation_infos(model_klass, relation_type)
relations = []
return relations unless
['has_one',
'belongs_to',
'has_many'].include?(relation_type.to_s.downcase) &&
model_klass.respond_to?(:reflect_on_all_associations)
model_klass.reflect_on_all_associations(relation_type)\
.collect do |association|
association_name = association.name
# Get the default association name, or the specified one in options hash.
if association.options.key?(:class_name)
klass_name = association.options[:class_name]
else
klass_name = association_name.to_s.singularize.camelize
end
klass = klass_name.to_s.constantize
# Get the default foreign key, or the specified one in options hash.
if association.options.key?(:foreign_key)
foreign_key = association.options[:foreign_key]
else
foreign_key = "#{klass.table_name.singularize}_id"
end
return {
association_name: association_name,
association_klass_name: klass_name,
association_klass: klass,
foreign_key: foreign_key
}
end
end
# Examples
# ========
def belongs_to_infos(model_klass)
relation_infos(model_klass, :belongs_to)
end
def has_one_infos(model_klass)
relation_infos(model_klass, :has_one)
end
def has_many_infos(model_klass)
relation_infos(model_klass, :has_many)
end
puts 'Belongs to relations for User'
belongs_to_infos(User)
puts 'Has one relations for User'
has_one_infos(User)
puts 'Has many relations for User'
has_many_infos(User)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment