-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add if/unless options to attribute #1266
Conversation
54c9151
to
b8f54ae
Compare
attrs = attrs.first if attrs.first.class == Array | ||
|
||
attrs.each do |attr| | ||
attribute(attr) | ||
attribute(attr, options) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we should support any options for attributes
. That's always just a list. We use attribute
for an attribute with options
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You want to use
attribute :id, if: :admin?
attribute :titile, if: :admin?
instead of attributes :id, :title, if: :admin?
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bf4 I'm not sure I understand why we would not want to support options for attributes
. Could you elaborate?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
value to end-user is minimal, cost to library is relatively high
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would usually agree, but since we already support variable number of arguments and array of symbols as parameters to attributes
, I don't believe the added cost is that high.
Thanks for this. This is a great feature! And has tests! I personally don't think this is a good thing for AMS to support right now. I also don't think the overhead of supporting in on attributes :banana, :tofu, :burger
def banana
object.banana || ExcludedAttribute # can't use nil since that's a valid value
# or
object.banana || ExcludedAttribute.new(:banana) # can't use nil since that's a valid value
# or
object.banana || :excluded_attribute
# or
condition ? object.banana : :excluded_attribute
end
def tofu
condition ? object.tofu : WhitelistedAttribute.new(object.tofu) # dunno, just thinking here
end such that the if banana is ExcludedAttribute, attribute keys will be tofu and burger. If tofu is WhitelistedAttribute, then only tofu is a WhitelistedAttribute, then only other whitelisted attribute keys are used, so only tofu will be in the attributes. That way the feature just requires a value-check in the attributes method and the condition logic is easy to use, and maybe could lead to the suggested interface. Also, I prefer |
Although I am currently not convinced which way is better, it seems lots of people are expecting a feature similar to this one. |
@beauby you're right about only/except. I must have been thinking of something else, like |
Would this work for associations as well? For example:
I think it would be more consistent to support both with the same syntax.
|
@@ -171,8 +186,31 @@ def attributes | |||
end | |||
end | |||
|
|||
def useless_attributes_keys |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
excluded_attribute_keys
might be a better name here.
A bit more work needed, but I'm personally favorable to this implementation. People are clearly expecting such a feature, and this appears to me as the sanest way to go around it. |
IMHO, this needs to be much simpler. It introduces a lot of complexity (in understanding and maintaining the code, in addition to vectors for bugs) for what could be solved either by polymorphism or by some non-nil value that means 'remove this key'. A non-nil value that means 'include this key' is more complicated to consider. |
The non-nil value that means 'exclude this key' puts too much of a burden on the user I think. Could you elaborate on the polymorphism solution? Do you mean subclassing the serializer into various flavors? If so, although I would personally go this way in my projects, several users have expressed their need for conditionally excluding many attributes depending on different conditions, which is a situation in which the polymorphism approach does not scale well (it takes an exponential number of serializers). |
I don't think any library should do everything
|
@bf4 True, but since this library used to do exactly that, I think we need a better reason than that. |
Just being philosophical here, but I'm not sure that a feature having been
removed from a library is an argument that it belongs
|
255feb6
to
0436ec6
Compare
I had updated the code. 😋 @beauby |
3043dab
to
bb27c7c
Compare
bb27c7c
to
f565241
Compare
I was using the filter feature to protect attributes in my API. Now that it is gone in 0.10, is there a way to omit certain attributes? Am I supposed to have two serializers one with the attributes and one without? Should I have three serializers to replace this functionality, a base class serializer that the protected and non-protected serializers inherit from? I don't understand why we can't have I need a solution to get this type of functionality back. class UserSerializer < ActiveModel::Serializer
attributes :id, :name, :email, :settings, :info, :token
def filter(keys)
unless object == scope
keys -= [:settings, :email, :token]
end
keys
end
end If there is another way to omit keys based on the object and scope, I'd love to know. If there is no way to do this with 0.10 rc3, let me know and I'll downgrade. |
I found a solution that kind of works. My solution does not remove the attribute, but instead nullifies the value. I don't think this is a pretty solution, but it will have to do for now. class UserSerializer < ActiveModel::Serializer
[:email, :settings, :token].each do |a|
define_method(a) do
object == scope ? object.send(a) : nil
end
end
attributes :id, :name, :email, :settings, :info, :token
end |
No description provided.