diff --git a/README.md b/README.md index 6f33ad1..8f77f6b 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,9 @@ Say, for example, you have a basic Food model: ```ruby class Food < ActiveRecord::Base include RocketPants::Cacheable + + # Only expose the following attributes in the API JSON response + attr_expose :name, :calories end ``` diff --git a/lib/rocket_pants.rb b/lib/rocket_pants.rb index c3a0472..a88ca96 100644 --- a/lib/rocket_pants.rb +++ b/lib/rocket_pants.rb @@ -22,6 +22,9 @@ module RocketPants autoload :Cacheable, 'rocket_pants/cacheable' autoload :CacheMiddleware, 'rocket_pants/cache_middleware' + # Model + autoload :Presenter, 'rocket_pants/presenter' + # Helpers for various testing frameworks. autoload :TestHelper, 'rocket_pants/test_helper' autoload :RSpecMatchers, 'rocket_pants/rspec_matchers' diff --git a/lib/rocket_pants/base.rb b/lib/rocket_pants/base.rb index 9d5affb..c961905 100644 --- a/lib/rocket_pants/base.rb +++ b/lib/rocket_pants/base.rb @@ -28,6 +28,7 @@ class Base < ActionController::Metal ActionController::Rescue, ErrorHandling, Rescuable, + Presenter, JSONP # FormatVerification # TODO: Implement Format Verification ].compact diff --git a/lib/rocket_pants/presenter.rb b/lib/rocket_pants/presenter.rb new file mode 100644 index 0000000..2972dfa --- /dev/null +++ b/lib/rocket_pants/presenter.rb @@ -0,0 +1,30 @@ +# Provides a way of selecting certain field attributes to present in the JSON response +module RocketPants + module Presenter + extend ActiveSupport::Concern + + included do + class_attribute :_presented_attributes + end + + module ClassMethods + # Accepts a list of attributes to be presented in the response + # + def attr_expose(*args) + options = args.extract_options! + self._presented_attributes = (self._presented_attributes || []) + args + end + end + + # Override to only show model attributes marked for presentation with attr_presented + def serializable_hash(options = {}) + options[:only] = (options[:only] || []) | (self.class._presented_attributes || []) + options[:only] = nil if options[:only].empty? + super(options) + end + + ActiveSupport.on_load :active_record do + ActiveRecord::Base.send :include, RocketPants::Presenter + end + end +end diff --git a/spec/rocket_pants/presenter_spec.rb b/spec/rocket_pants/presenter_spec.rb new file mode 100644 index 0000000..170e023 --- /dev/null +++ b/spec/rocket_pants/presenter_spec.rb @@ -0,0 +1,21 @@ +require 'spec_helper' +require 'rocket_pants/presenter' + +describe RocketPants::Presenter do + include ControllerHelpers + + use_reversible_tables :fish, :scope => :all + + it 'should provide an attr_exposed method on an AR model' do + Fish.respond_to?(:attr_expose).should be_true + end + + it 'should only expose certain attributes' do + attrs = {:token => "a", :name => "Test Fish", :latin_name => "Latin Name", :child_number => 5} + + Fish.attr_expose :name + + f = Fish.create! attrs + f.serializable_hash.keys.should == ["name"] + end +end \ No newline at end of file