Showing posts with label web application. Show all posts
Showing posts with label web application. Show all posts

Wednesday, February 4, 2015

Rails ActiveModel/ActiveRecord XML/JSON serialization replacement

I need a bit more control over the XML schema than the standard ActiveRecord/ActiveModel XML serializers provide, and a bit of control over root tags and attribute names in JSON that normally isn't there. I don't need the full control that something like RABL provides, and I'd like deserialization from XML to be automatically available for any XML I can serialize to. None of the existing gems provides what I want without having to hand-code methods on all classes involved, especially the deserialization part. And if I've written the deserialization code and have the hashes to control that, the serialization code based on those same hashes won't be that much additional work. The hard part will be eventually making it a drop-in replacement for the ActiveModel XML and JSON serializers and compatible with the parts of ActiveRecord that interact with serialization. I'll deal with that later, though, I'm just going to lay the groundwork for compatibility now and deal with actually integrating it once I've got the code working outside that framework.



XML serialization/deserialization description and control data:

Item hash:
  • name: element or attribute name
  • source: object attribute name, literal data string, nil for no contents
  • +type: Ruby class name, Boolean short for "TrueClass or FalseClass", Literal for a literal element (no source attribute), default String if this is not the root element or the class being deserialized for the root element
  • options: {options hash}, default {}
  • *attributes: [array of item hashes describing attributes of this element], default []
  • *children: [array of item hashes describing child elements of this element], default []
+ = needed only during deserialization
* = valid only in element item hashes, ignored in attribute item hashes

Options hash:
  • *default: default value if source's value is nil, default no value
  • trim: true/false, trim leading/trailing whitespace, default false
  • elide: true/false, omit if value (after trimming if relevant) is nil or empty, default false
* = not applicable to items of Literal type or items where source is nil.

Control attributes on the object:

xml_attributes: an item hash describing the root element of the object
  • Canonically the source would be nil, but a source attribute is legal if the root element will have actual text content.
  • The type attribute of the root element defaults to the type of the object if not specified, and canonically it isn't specified since forcing a mismatching type will cause problems.
  • The name attribute can be overridden by specifying an element name when serializing the object. When deserializing the root element's name is ignored and it's assumed the caller is deserializing the correct class.
attributes: a hash describing the attributes to be serialized
  • The key is the source attribute name.
  • The value is nil or a string giving the element name to be used.
If xml_attributes is not present, attributes will be used instead. One or the other must be provided.

When serializing XML:
  • If attributes is used then the attributes are serialized as child elements of the root and the default for include_types is true and use_source_names is true if the value is nil and false if the value names an element name. If xml_attributes is used the default for include_types and use_source_names is false. This allows the XML to be unchanged if an old-style attributes hash is being used.
When serializing JSON:
  • If xml_attributes is used then the attributes sub-hash is serialized first followed by the children sub-hash. Items with a nil source or Literal for type are ignored, they're relevant only to XML serialization.
  • When deserializing, if type is absent then the type is determined by Ruby's default rules and the format of the value. Contained objects will end up deserialized to a hash and a class-specific attributes= method will be needed to recognize the attribute name, create an object of the correct class and initialize it with the hash before assigning it to the attribute.
to_xml options:
  • root_name: name of the root element if not the class name of the object
  • include_types: include type and nil attributes in XML
  • use_source_names: follow Ruby's naming conventions for element names
root_name is normally used when attributes is used to control serialization, or if the root element name in xml_attributes needs to be overridden. Setting both include_types and use_source_names to true will yield the same XML normally produced by the old serializer when using xml_attributes .

to_json options:
  • include_root_in_json: include the class name as the root element of the JSON representation, default false
  • include_all_roots_in_json: include the class name as the root element for all contained objects (implies include_root_in_json), default false
include_root_in_json only puts the root element in at the top level, not on contained objects. That makes it compatible with the JSON expected when the matching flag is set in the from_json call.

Monday, April 4, 2011

ASP.Net ViewState

Really really dumb idea: using a complex, high-overhead ViewState mechanism to set field values in the Web page returned from posting a form instead of simply setting the field values in the returned page. I mean, the posted page has the values populated, that's it's whole purpose. So when generating the response page, simply set the value attributes to what the fields' values were in the post request. Simple, no? Apparently not for Microsoft.

Friday, April 2, 2010

Quake 2 in HTML5

OK, this just takes the cake. They've ported Quake 2 into HTML5 using a ton of JavaScript and such. Details on the developer's web site. I am amazed.

Wednesday, December 3, 2008

BodyParts webapp

I finished the first pass at the BodyParts webapp that lets me view and maintain the Legends&Lore body parts inventory for my guild in EQ2. Security framework enabled, anonymous viewing and a login for editing, Tomcat set up properly, Apache configured to front for it. Now I can update the inventory from the in-game browser, no more writing things down on paper and windowing out to update text files.

Next things on the list:
  • Add add/subtract fields and buttons to the editing screen so that instead of having to do the math in my head I can just punch in the number of parts and hit Add or Subtract depending on whether I'm depositing or withdrawing parts.
  • Move the inventory from an XML data file into a real database table. I'll want to move the user information into a database table in the process and change authentication to match.
  • Reconfigure things to have all webapps in their own sub-tree so they don't sit directly at the root of the content tree. I'll have to see whether I want Apache to re-write URLs (so the user sees /webapp/BodyParts/ while Tomcat sees just /BodyParts/) or whether I want to make the change within Tomcat.
  • Change things in Eclipse to not depend on MyEclipse for the Spring framework and supporting libraries. I'm finding that as I get more familiar with things it's easier to edit the XML directly than to depend on MyEclipse's tools.
It's been a useful excercise so far.

Wednesday, November 5, 2008

BodyParts webapp

Slowly but surely I'm getting my head around writing a web app using the Spring framework. It's requiring a fair amount of work, but it's much easier to understand when I'm actually writing code and seeing it work (or, more often, fail miserably). I need to get error handling working, then adding a new species, and then adding the security bits to allow some users to edit and others to only view the data. Once I'm done I'll not only have a handle on Spring, I'll have a way to edit my guild's body-parts database while I'm in-game.