Skip to content
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

FlattenJson adapter no longer inherits Json adapter, renamed to Attributes #1117

Merged

Conversation

bf4
Copy link
Member

@bf4 bf4 commented Sep 4, 2015

  • FlattenJson adapter no longer inherits Json adapter
  • Rename FlattenJson to Attributes (allow plural adapter names)
  • Consistently refer to the 'JSON API' and the 'JsonApi' adapter

TODO

  • Add to changelog

@beauby
Copy link
Contributor

beauby commented Sep 4, 2015

👍

@bf4
Copy link
Member Author

bf4 commented Sep 4, 2015

@beauby Thanks. I followed a somewhat non-linear path to get there, which is why I extracted CacheCheck along the way, but decided is was fine :)

@@ -10,7 +10,7 @@ AMS does this through two components: **serializers** and **adapters**.
Serializers describe _which_ attributes and relationships should be serialized.
Adapters describe _how_ attributes and relationships should be serialized.

By default AMS will use the **Flatten Json Adapter**. But we strongly advise you to use **JsonApi Adapter** that follows 1.0 of the format specified in [jsonapi.org/format](http://jsonapi.org/format).
By default AMS will use the **Attributes Adapter**. But we strongly advise you to use **JsonApi Adapter** that follows 1.0 of the format specified in [jsonapi.org/format](http://jsonapi.org/format).
Check how to change the adapter in the sections bellow.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thing that I don't like about calling the adapter attributes is that it is harder to grep for, esp if we want to rename it again. But, we liked the name in the Slack channel, so until something better..

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yup, I'm not sure about the name as well, but have no suggestions so far

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AttributeSerialization?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fields, Properties?? idk. ha

autoload :Null
autoload :FragmentCache

include CacheCheck
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are using autoload and including it in the sequence, shouldn't we go with require instead then?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good point :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

@joaomdmoura
Copy link
Member

Nice work here @bf4, really fast! Can you check the comments and rebase it please ? 😄

@bf4 bf4 force-pushed the remove_flatten_json_inheriting_json branch from 40a1daa to fb92d25 Compare September 7, 2015 22:23
@bf4
Copy link
Member Author

bf4 commented Sep 7, 2015

cleaned up

@bf4 bf4 changed the title FlattenJson adapter no longer inherits Json adapter FlattenJson adapter no longer inherits Json adapter, renamed to Attributes Sep 11, 2015
@bf4 bf4 mentioned this pull request Sep 11, 2015
@NullVoxPopuli
Copy link
Contributor

needs rebase

@NullVoxPopuli
Copy link
Contributor

Why not inherit from the json adapter?

@bf4
Copy link
Member Author

bf4 commented Sep 13, 2015

Can't. Would need to undef methods

@NullVoxPopuli
Copy link
Contributor

why?

this is just so clean:

    def serializable_hash(options = {})
      super.each_value.first
    end

my concern is that duplicating code is prone to errors and repeated bugs

@bf4
Copy link
Member Author

bf4 commented Sep 13, 2015

@NullVoxPopuli asked:

Why not inherit from the json adapter?

Because, if anything, FlattenJson/Attributes is the super class. It's a more general case.

I knew someone who preferred inheritance over composition. He was a super guy.

+        def serializable_hash(options = {})
+          { root => Adapter::Attributes.new(serializer).serializable_hash(options) }

Nice eh?

Aside: adapters and serializers should both have their own meta, the adapter's going at the top level. serializer.meta should be part of Attributes. http://jsonapi.org/format/#document-resource-objects

@NullVoxPopuli
Copy link
Contributor

Because, if anything, FlattenJson/Attributes is the super class. It's a more general case.

Maybe the common functionality could be pulled out in to a module then? or a class that both inherit from?

I know inheritance isn't the answer for everything, but I do hate duplicate code.

also, I hate combining that sort of stuff in to one line..
I would have done:

def serializable_hash(options = {})
  adapter = Adapter::attributes.new(serializer)
  serialized = adapter.serializable_hash(options)

  { root => serialized }

much cleaner :-) and easier to debug.

But anyway, with the upcoming Adapter::Base changes, I'm hoping to eventually move JSON stuff in there as well.

I think there is a way to use json api and json such that they pass blocks to 'Base' for there specific different formats

@bf4
Copy link
Member Author

bf4 commented Sep 13, 2015

Maybe the common functionality could be pulled out in to a module then? or a class that both inherit from?

Modules are inheritance. I'm not even sure how that would work without having two subclasses that include such a module if we want to keep the abstract methods in Adapter.

I know inheritance isn't the answer for everything, but I do hate duplicate code.

Where's the duplicate code. I'm not seeing it :)

@bf4 bf4 force-pushed the remove_flatten_json_inheriting_json branch from fb92d25 to b592ebc Compare September 13, 2015 14:51
@bf4
Copy link
Member Author

bf4 commented Sep 13, 2015

Rebased

resource[:relationships][name] ||= { data: [] }
resource[:relationships][name][:data] += serializers.map { |serializer| { type: serializer.json_api_type, id: serializer.id.to_s } }
end

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was accidentally re-introduced in a rebased PR

@NullVoxPopuli
Copy link
Contributor

needs rebase.

But.. I think I am ok with these changes -- I like the separation of responsibility for attributes. Hopefully this will help cleanup #1127 as well.

@bf4 bf4 force-pushed the remove_flatten_json_inheriting_json branch from a144f55 to c6f8d0f Compare September 18, 2015 15:17
@NullVoxPopuli
Copy link
Contributor

👍

NullVoxPopuli added a commit that referenced this pull request Sep 18, 2015
FlattenJson adapter no longer inherits Json adapter, renamed to Attributes
@NullVoxPopuli NullVoxPopuli merged commit a309132 into rails-api:master Sep 18, 2015
@bf4 bf4 deleted the remove_flatten_json_inheriting_json branch September 18, 2015 16:56
@jfelchner
Copy link
Contributor

Hey guys, I just tried rebasing #1029 and ran into this. Can someone explain to me what benefit was provided by doing this as opposed to either:

a) Leaving it as it was. After all FlattenJson was a more specific Json adapter and therefore inheritance made sense IMO.
b) Creating a module that both adapters inherit from with the common functionality.

In all three scenarios (including the changes in this PR) there is no duplicated code anywhere.

Now effectively any adapter-specific options/defaults need to be explicitly parsed before passing them into the Attributes adapter. Whereas if we'd used inheritance everything would Just Work because it would be using the appropriate values for whatever class it was instantiated as.

I favor composition the majority of the time, but I don't think this one is appropriate.

I personally think we should instead break the serializable_hash method down into about a dozen smaller methods, and keep them on the Json adapter. If the Json adapter's root is nil then there's no root (and no allowed meta). Then the Attributes adapter can be completely removed.

As a concrete example, this is causing major problems for me rebasing #1029 and I don't like the solution nearly as much as I did before. IMO it's much less elegant.

@bf4
Copy link
Member Author

bf4 commented Sep 20, 2015

@jfelchner

I personally think we should instead break the [Adapter#]serializable_hash method down into about a dozen smaller methods,

Totally agree

and keep them on the Json adapter.

I get what you're saying, but the Json adapter is, I think, the wrong place

If the Json adapter's root is nil then there's no root (and no allowed meta). Then the Attributes adapter can be completely removed.

True. I agree there's got to be a better division of reponsibilities, but is the Json adapter the same as Attributes, but only with a root and meta data? That's certainly how the code looks now, but will it continue to be true?

For the moment, it's simpler, I think, for the Json adapter to use the Attributes adapter than to worry about which adapter should inherit which. I'm also not convinced that mixing in an 'AttributesSerialization' module to both the Attributes Adapter and the Json Adapter improves on this.

Here's how I'm thinking of the pieces now:

  • A model/resource has attributes that are 'readable for serialization'.
    • (We should really document that read_attribute_for_serialization(name) could be used for any user-controlled transformations in the model...
  • A Serializer for the model that expresses the desired attributes and any transformations of the model's attributes
  • The Attributes adapter more or less passes through the serializer attributes into the serializable hash, except that it also handles collections.
  • The other adapters use the serialization (via the Attributes adapter) of the models and any other input or options to build the response document aka serializable_hash

(or something like that)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants