|
# Provide a system for specifying private attributes that shouldn't be exposed |
|
module ActiveRecord |
|
class Base |
|
class << self |
|
|
|
# Instead of setting the instance variable when this is called, we only check |
|
# if it's defined. It's only set when attr_private is called. This allows us |
|
# to know if the model has ever set any private attributes or not |
|
def private_attributes |
|
instance_variable_defined?('@private_attributes') ? @private_attributes : [] |
|
end |
|
|
|
def is_private_attribute?(name) |
|
private_attributes.include?(name.to_sym) |
|
end |
|
|
|
protected |
|
|
|
# Set the @private_attributes variable with an array of attribute symbols |
|
def attr_private(*args) |
|
(@private_attributes ||= []).push(*args.collect { |a| a.to_sym }).uniq! |
|
end |
|
|
|
# Specify public attributes, which conversely privatizes the other attributes |
|
# If private attributes have previously been declared, attr_public can override |
|
# the setting. If it is the first time, make all the attributes private unless |
|
# they are in the args. |
|
def attr_public(*args) |
|
if instance_variable_defined?('@private_attributes') && !@private_attributes.empty? |
|
@private_attributes.delete_if { |n| args.include?(n.to_sym) } |
|
else |
|
attr_private(*attribute_names.reject { |n| args.include?(n.to_sym) }) |
|
end |
|
end |
|
end |
|
|
|
# Run the to_xml options through a filter |
|
def to_xml(options={}) |
|
super(secure_private_options(options)) |
|
end |
|
|
|
# Run the serializable_hash options through a filter |
|
def serializable_hash(options={}) |
|
super(secure_private_options(options)) |
|
end |
|
|
|
protected |
|
|
|
# Filter the options to make sure private attributes aren't included |
|
def secure_private_options(options={}) |
|
(options[:except] ||= []).push(*self.class.private_attributes) |
|
options[:only].delete_if { |n| self.class.is_private_attribute?(n) } if options.has_key?(:only) |
|
options[:methods].delete_if { |n| self.class.is_private_attribute?(n) } if options.has_key?(:methods) |
|
options |
|
end |
|
end |
|
end |
|
|
|
# Modify Rabl's builder to check if a method is private before exposing it |
|
module Rabl |
|
class Builder |
|
protected |
|
# Don't output the |
|
def attribute(name, options={}) |
|
unless @_object.class.respond_to?(:is_private_attribute?) && @_object.class.is_private_attribute?(name) |
|
@_result[options[:as] || name] = data_object_attribute(name) if @_object && @_object.respond_to?(name) |
|
end |
|
end |
|
end |
|
end |