Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

introduced :if and :unless options to associations

  • Loading branch information...
commit afe54e8550e62d502c7405e8421784c3921651ec 1 parent 0ed9929
@dgeb authored
Showing with 159 additions and 76 deletions.
  1. +34 −24 lib/active_model/serializer.rb
  2. +125 −52 test/serializer_test.rb
View
58 lib/active_model/serializer.rb
@@ -232,12 +232,12 @@ def serialize_ids
class_attribute :_attributes
self._attributes = {}
- class_attribute :_attribute_options
- self._attribute_options = {}
-
class_attribute :_associations
self._associations = {}
+ class_attribute :_field_options
+ self._field_options = {}
+
class_attribute :_root
class_attribute :_embed
self._embed = :objects
@@ -256,11 +256,11 @@ def attributes(*attrs)
def attribute(attr, options={})
self._attributes = _attributes.merge(attr => options[:key] || attr)
if options[:if] || options[:unless] || options[:value]
- self._attribute_options = _attribute_options.dup
+ self._field_options = _field_options.dup
[:if, :unless, :value].each do |opt|
if options[opt]
- self._attribute_options[opt] ||= {}
- self._attribute_options[opt][attr] = options[opt]
+ self._field_options[opt] ||= {}
+ self._field_options[opt][attr] = options[opt]
end
end
end
@@ -270,6 +270,18 @@ def associate(klass, attrs) #:nodoc:
options = attrs.extract_options!
self._associations = _associations.dup
+ if options[:if] || options[:unless]
+ self._field_options = _field_options.dup
+ [:if, :unless].each do |opt|
+ if options[opt]
+ attrs.each do |attr|
+ self._field_options[opt] ||= {}
+ self._field_options[opt][attr] = options[opt]
+ end
+ end
+ end
+ end
+
attrs.each do |attr|
unless method_defined?(attr)
class_eval "def #{attr}() object.#{attr} end", __FILE__, __LINE__
@@ -413,13 +425,15 @@ def serializable_hash
def include_associations!(node)
_associations.each do |attr, klass|
- opts = { :node => node }
+ if include_field?(attr)
+ opts = { :node => node }
- if options.include?(:include) || options.include?(:exclude)
- opts[:include] = included_association?(attr)
- end
+ if options.include?(:include) || options.include?(:exclude)
+ opts[:include] = included_association?(attr)
+ end
- include! attr, opts
+ include! attr, opts
+ end
end
end
@@ -496,10 +510,10 @@ def merge_association(hash, key, value, unique_values)
end
end
- def include_attribute?(name)
+ def include_field?(name)
[:if, :unless].each do |opt|
- if self._attribute_options.key?(opt) && self._attribute_options[opt].include?(name)
- ret = eval_attribute_option_value(self._attribute_options[opt][name])
+ if self._field_options.key?(opt) && self._field_options[opt].include?(name)
+ ret = eval_attribute_option_value(self._field_options[opt][name])
return (opt == :if) ? ret : !ret
end
end
@@ -507,14 +521,6 @@ def include_attribute?(name)
true
end
- def attribute_value(name)
- if self._attribute_options.key?(:value) && self._attribute_options[:value].include?(name)
- eval_attribute_option_value(self._attribute_options[:value][name])
- else
- @object.read_attribute_for_serialization(name)
- end
- end
-
def eval_attribute_option_value(value)
if value.respond_to? :call
value.call(self)
@@ -533,8 +539,12 @@ def attributes
hash = {}
_attributes.each do |name, key|
- if include_attribute?(name)
- hash[key] = attribute_value(name)
+ if include_field?(name)
+ hash[key] = if self._field_options.key?(:value) && self._field_options[:value].include?(name)
+ eval_attribute_option_value(self._field_options[:value][name])
+ else
+ @object.read_attribute_for_serialization(name)
+ end
end
end
View
177 test/serializer_test.rb
@@ -70,52 +70,6 @@ def serializable_hash
end
end
- class IfSerializer < ActiveModel::Serializer
- root :user
-
- attribute :first_name, :if => :first_name?
- attribute :last_name, :if => lambda { |s| s.last_name? }
- attribute :password, :if => :super_user?
-
- def first_name?
- true
- end
- def last_name?
- false
- end
- end
-
- class UnlessSerializer < ActiveModel::Serializer
- root :user
-
- attribute :first_name, :unless => :first_name?
- attribute :last_name, :unless => lambda { |s| s.last_name? }
- attribute :password, :unless => :super_user?
-
- def first_name?
- true
- end
- def last_name?
- false
- end
- end
-
- class ValueSerializer < ActiveModel::Serializer
- root :user
-
- attribute :first_name, :value => :lower_first_name
- attribute :last_name, :value => lambda { |s| s.upper_last_name }
- attribute :admin, :value => :super_user?
- attribute :static, :value => "constant"
-
- def lower_first_name
- @object.read_attribute_for_serialization(:first_name).downcase
- end
- def upper_last_name
- @object.read_attribute_for_serialization(:last_name).upcase
- end
- end
-
class CommentSerializer
def initialize(comment, scope, options={})
@comment, @scope = comment, scope
@@ -537,10 +491,25 @@ def test_attribute_key
}, serializer.as_json)
end
- def test_attribute_that_uses_if
+ def test_attribute_defined_with_if
+ serializer_class = Class.new(ActiveModel::Serializer) do
+ root :user
+
+ attribute :first_name, :if => :show_first_name?
+ attribute :last_name, :if => lambda { |s| s.show_last_name? }
+ attribute :password, :if => :super_user?
+
+ def show_first_name?
+ true
+ end
+ def show_last_name?
+ false
+ end
+ end
+
u = User.new
u.superuser = true
- serializer = IfSerializer.new(u)
+ serializer = serializer_class.new(u)
assert_equal({
:user => {
@@ -550,10 +519,25 @@ def test_attribute_that_uses_if
}, serializer.as_json)
end
- def test_attribute_that_uses_unless
+ def test_attribute_defined_with_unless
+ serializer_class = Class.new(ActiveModel::Serializer) do
+ root :user
+
+ attribute :first_name, :unless => :hide_first_name?
+ attribute :last_name, :unless => lambda { |s| s.hide_last_name? }
+ attribute :password, :unless => :super_user?
+
+ def hide_first_name?
+ true
+ end
+ def hide_last_name?
+ false
+ end
+ end
+
u = User.new
u.superuser = true
- serializer = UnlessSerializer.new(u)
+ serializer = serializer_class.new(u)
assert_equal({
:user => {
@@ -562,10 +546,26 @@ def test_attribute_that_uses_unless
}, serializer.as_json)
end
- def test_attribute_that_uses_value
+ def test_attribute_that_specifies_value
+ serializer_class = Class.new(ActiveModel::Serializer) do
+ root :user
+
+ attribute :first_name, :value => :lower_first_name
+ attribute :last_name, :value => lambda { |s| s.upper_last_name }
+ attribute :admin, :value => :super_user?
+ attribute :static, :value => "constant"
+
+ def lower_first_name
+ @object.read_attribute_for_serialization(:first_name).downcase
+ end
+ def upper_last_name
+ @object.read_attribute_for_serialization(:last_name).upcase
+ end
+ end
+
u = User.new
u.superuser = true
- serializer = ValueSerializer.new(u)
+ serializer = serializer_class.new(u)
assert_equal({
:user => {
@@ -900,4 +900,77 @@ def test_embed_with_include_inserts_at_root
]
}, actual)
end
+
+ def test_association_conditionals
+ user_serializer = Class.new(ActiveModel::Serializer) do
+ embed :ids, :include => true
+ attributes :id, :name
+ end
+
+ comment_serializer = Class.new(ActiveModel::Serializer) do
+ embed :ids, :include => true
+ attributes :id, :body
+ end
+
+ post_serializer = Class.new(ActiveModel::Serializer) do
+ embed :ids, :include => true
+ attributes :id, :title, :body
+ has_many :comments, :serializer => comment_serializer, :if => :comment_reader?
+ has_one :author, :serializer => user_serializer, :unless => :anonymous?
+
+ def comment_reader?
+ options[:scope][:comment_reader]
+ end
+
+ def anonymous?
+ options[:scope][:anonymous]
+ end
+ end
+
+ post_class = Class.new(Model) do
+ attr_accessor :comments, :author
+
+ define_method :active_model_serializer do
+ post_serializer
+ end
+ end
+
+ comment_class = Class.new(Model) do
+ end
+
+ user_class = Class.new(Model) do
+ end
+
+ steinbeck = user_class.new(:name => "John Steinbeck", :id => 1)
+
+ comment1 = comment_class.new(:body => "EWOT", :id => 1)
+ comment2 = comment_class.new(:body => "YARLY", :id => 2)
+
+ post = post_class.new(:title => "New Post", :body => "NEW POST", :id => 1)
+ post.author = steinbeck
+ post.comments = [comment1, comment2]
+
+ actual = ActiveModel::ArraySerializer.new([post], :root => :posts,
+ :scope => {:comment_reader => true, :anonymous => false}).as_json
+ assert_equal({
+ :posts => [
+ { :title => "New Post", :body => "NEW POST", :id => 1, :comments => [1,2], :author => 1 }
+ ],
+ :authors => [
+ { :name => "John Steinbeck", :id => 1 },
+ ],
+ :comments => [
+ { :body => "EWOT", :id => 1 },
+ { :body => "YARLY", :id => 2 }
+ ]
+ }, actual)
+
+ actual = ActiveModel::ArraySerializer.new([post], :root => :posts,
+ :scope => {:comment_reader => false, :anonymous => true}).as_json
+ assert_equal({
+ :posts => [
+ { :title => "New Post", :body => "NEW POST", :id => 1 }
+ ]
+ }, actual)
+ end
end
Please sign in to comment.
Something went wrong with that request. Please try again.