I'm writing an API wrapper in Ruby for the Omeka API. Part of the API is making a class that represents an item on the Omeka site. A GET request to the API returns a JSON object, which I convert to a hash (see below, since it's long). Rather than making users navigate through a long hash, I'm using the Recursive Open Struct gem to create accessor methods. For example:
class OmekaItem
attr_accessor :data
def initialize(hash)
@data = RecursiveOpenStruct.new(hash, :recurse_over_arrays => true)
end
end
Assuming that I've made an instance of the class called item
that lets the user access data like so: item.data.id
or item.data.modified
.
The most important data is in the element texts array. There are two kinds of element texts: "Dublin Core" and "Item Type Metadata." I'd like to create a separate Open Struct for the data in those fields. This is how I do that:
class OmekaItem
attr_accessor :data, :dublin_core, :item_type_metadata
def initialize(hash)
@data = RecursiveOpenStruct.new(hash, :recurse_over_arrays => true)
dublin_core = Hash.new
item_type_metadata = Hash.new
@data.element_texts.each do |element_text|
if element_text.element_set.name == "Dublin Core"
method_name = element_text.element.name.downcase.gsub(/\s/, '_')
value = element_text.text
dublin_core[method_name] = value
elsif element_text.element_set.name == "Item Type Metadata"
method_name = element_text.element.name.downcase.gsub(/\s/, '_')
value = element_text.text
item_type_metadata[method_name] = value
end
end
@dublin_core = RecursiveOpenStruct.new(dublin_core)
@item_type_metadata = RecursiveOpenStruct.new(item_type_metadata)
end
end
Now users can access the Dublin Core metadata with method calls like this: item.dublin_core.title
.
So far so good, but this is where I'm stuck. The class needs to implement a to_h
method to return a hash in the original format with changed data, so that I can pass it to POST and PUT methods. If someone were to change the data by calling item.data.element_text[1].text = "My new data"
then I could easily call the method on the open struct that returns a hash. But if a user changes item.dublin_core.title = "My new title"
that data will be separate from the open struct stored in @data
. How can I go about making the two places where the data is stored line up?
A typical hash for an item looks like this:
>> pp hash
{"id"=>1,
"url"=>"http://localhost/omeka-2.1-rc1/api/items/1",
"public"=>true,
"featured"=>false,
"added"=>"2013-07-13T04:47:08+00:00",
"modified"=>"2013-07-14T19:37:45+00:00",
"item_type"=>
{"id"=>10,
"url"=>"http://localhost/omeka-2.1-rc1/api/item_types/10",
"name"=>"Lesson Plan",
"resource"=>"item_types"},
"collection"=>
{"id"=>1,
"url"=>"http://localhost/omeka-2.1-rc1/api/collections/1",
"resource"=>"collections"},
"owner"=>
{"id"=>1,
"url"=>"http://localhost/omeka-2.1-rc1/api/users/1",
"resource"=>"users"},
"files"=>
{"count"=>0,
"url"=>"http://localhost/omeka-2.1-rc1/api/files?item=1",
"resource"=>"files"},
"tags"=>[],
"element_texts"=>
[{"html"=>false,
"text"=>"Item Title",
"element_set"=>
{"id"=>1,
"url"=>"http://localhost/omeka-2.1-rc1/api/element_sets/1",
"name"=>"Dublin Core",
"resource"=>"element_sets"},
"element"=>
{"id"=>50,
"url"=>"http://localhost/omeka-2.1-rc1/api/elements/50",
"name"=>"Title",
"resource"=>"elements"}},
{"html"=>false,
"text"=>"Item Subject",
"element_set"=>
{"id"=>1,
"url"=>"http://localhost/omeka-2.1-rc1/api/element_sets/1",
"name"=>"Dublin Core",
"resource"=>"element_sets"},
"element"=>
{"id"=>49,
"url"=>"http://localhost/omeka-2.1-rc1/api/elements/49",
"name"=>"Subject",
"resource"=>"elements"}},
{"html"=>false,
"text"=>"Item Contributor",
"element_set"=>
{"id"=>1,
"url"=>"http://localhost/omeka-2.1-rc1/api/element_sets/1",
"name"=>"Dublin Core",
"resource"=>"element_sets"},
"element"=>
{"id"=>37,
"url"=>"http://localhost/omeka-2.1-rc1/api/elements/37",
"name"=>"Contributor",
"resource"=>"elements"}},
{"html"=>true,
"text"=>"Item Description",
"element_set"=>
{"id"=>1,
"url"=>"http://localhost/omeka-2.1-rc1/api/element_sets/1",
"name"=>"Dublin Core",
"resource"=>"element_sets"},
"element"=>
{"id"=>41,
"url"=>"http://localhost/omeka-2.1-rc1/api/elements/41",
"name"=>"Description",
"resource"=>"elements"}},
{"html"=>true,
"text"=>"Item Creator",
"element_set"=>
{"id"=>1,
"url"=>"http://localhost/omeka-2.1-rc1/api/element_sets/1",
"name"=>"Dublin Core",
"resource"=>"element_sets"},
"element"=>
{"id"=>39,
"url"=>"http://localhost/omeka-2.1-rc1/api/elements/39",
"name"=>"Creator",
"resource"=>"elements"}},
{"html"=>false,
"text"=>"Item Source",
"element_set"=>
{"id"=>1,
"url"=>"http://localhost/omeka-2.1-rc1/api/element_sets/1",
"name"=>"Dublin Core",
"resource"=>"element_sets"},
"element"=>
{"id"=>48,
"url"=>"http://localhost/omeka-2.1-rc1/api/elements/48",
"name"=>"Source",
"resource"=>"elements"}},
{"html"=>false,
"text"=>"Item Publisher",
"element_set"=>
{"id"=>1,
"url"=>"http://localhost/omeka-2.1-rc1/api/element_sets/1",
"name"=>"Dublin Core",
"resource"=>"element_sets"},
"element"=>
{"id"=>45,
"url"=>"http://localhost/omeka-2.1-rc1/api/elements/45",
"name"=>"Publisher",
"resource"=>"elements"}},
{"html"=>false,
"text"=>"Item Date",
"element_set"=>
{"id"=>1,
"url"=>"http://localhost/omeka-2.1-rc1/api/element_sets/1",
"name"=>"Dublin Core",
"resource"=>"element_sets"},
"element"=>
{"id"=>40,
"url"=>"http://localhost/omeka-2.1-rc1/api/elements/40",
"name"=>"Date",
"resource"=>"elements"}},
{"html"=>false,
"text"=>"Item Rights",
"element_set"=>
{"id"=>1,
"url"=>"http://localhost/omeka-2.1-rc1/api/element_sets/1",
"name"=>"Dublin Core",
"resource"=>"element_sets"},
"element"=>
{"id"=>47,
"url"=>"http://localhost/omeka-2.1-rc1/api/elements/47",
"name"=>"Rights",
"resource"=>"elements"}},
{"html"=>false,
"text"=>"Item Relation",
"element_set"=>
{"id"=>1,
"url"=>"http://localhost/omeka-2.1-rc1/api/element_sets/1",
"name"=>"Dublin Core",
"resource"=>"element_sets"},
"element"=>
{"id"=>46,
"url"=>"http://localhost/omeka-2.1-rc1/api/elements/46",
"name"=>"Relation",
"resource"=>"elements"}},
{"html"=>false,
"text"=>"Item Format",
"element_set"=>
{"id"=>1,
"url"=>"http://localhost/omeka-2.1-rc1/api/element_sets/1",
"name"=>"Dublin Core",
"resource"=>"element_sets"},
"element"=>
{"id"=>42,
"url"=>"http://localhost/omeka-2.1-rc1/api/elements/42",
"name"=>"Format",
"resource"=>"elements"}},
{"html"=>false,
"text"=>"Item Language",
"element_set"=>
{"id"=>1,
"url"=>"http://localhost/omeka-2.1-rc1/api/element_sets/1",
"name"=>"Dublin Core",
"resource"=>"element_sets"},
"element"=>
{"id"=>44,
"url"=>"http://localhost/omeka-2.1-rc1/api/elements/44",
"name"=>"Language",
"resource"=>"elements"}},
{"html"=>false,
"text"=>"Item Type",
"element_set"=>
{"id"=>1,
"url"=>"http://localhost/omeka-2.1-rc1/api/element_sets/1",
"name"=>"Dublin Core",
"resource"=>"element_sets"},
"element"=>
{"id"=>51,
"url"=>"http://localhost/omeka-2.1-rc1/api/elements/51",
"name"=>"Type",
"resource"=>"elements"}},
{"html"=>false,
"text"=>"Item Identifier",
"element_set"=>
{"id"=>1,
"url"=>"http://localhost/omeka-2.1-rc1/api/element_sets/1",
"name"=>"Dublin Core",
"resource"=>"element_sets"},
"element"=>
{"id"=>43,
"url"=>"http://localhost/omeka-2.1-rc1/api/elements/43",
"name"=>"Identifier",
"resource"=>"elements"}},
{"html"=>false,
"text"=>"Item Coverage",
"element_set"=>
{"id"=>1,
"url"=>"http://localhost/omeka-2.1-rc1/api/element_sets/1",
"name"=>"Dublin Core",
"resource"=>"element_sets"},
"element"=>
{"id"=>38,
"url"=>"http://localhost/omeka-2.1-rc1/api/elements/38",
"name"=>"Coverage",
"resource"=>"elements"}},
{"html"=>false,
"text"=>"Item Type Duration",
"element_set"=>
{"id"=>3,
"url"=>"http://localhost/omeka-2.1-rc1/api/element_sets/3",
"name"=>"Item Type Metadata",
"resource"=>"element_sets"},
"element"=>
{"id"=>11,
"url"=>"http://localhost/omeka-2.1-rc1/api/elements/11",
"name"=>"Duration",
"resource"=>"elements"}},
{"html"=>false,
"text"=>"Item Type Standards",
"element_set"=>
{"id"=>3,
"url"=>"http://localhost/omeka-2.1-rc1/api/element_sets/3",
"name"=>"Item Type Metadata",
"resource"=>"element_sets"},
"element"=>
{"id"=>24,
"url"=>"http://localhost/omeka-2.1-rc1/api/elements/24",
"name"=>"Standards",
"resource"=>"elements"}},
{"html"=>false,
"text"=>"Item Type Objectives",
"element_set"=>
{"id"=>3,
"url"=>"http://localhost/omeka-2.1-rc1/api/element_sets/3",
"name"=>"Item Type Metadata",
"resource"=>"element_sets"},
"element"=>
{"id"=>25,
"url"=>"http://localhost/omeka-2.1-rc1/api/elements/25",
"name"=>"Objectives",
"resource"=>"elements"}},
{"html"=>false,
"text"=>"Item Type Materials",
"element_set"=>
{"id"=>3,
"url"=>"http://localhost/omeka-2.1-rc1/api/element_sets/3",
"name"=>"Item Type Metadata",
"resource"=>"element_sets"},
"element"=>
{"id"=>26,
"url"=>"http://localhost/omeka-2.1-rc1/api/elements/26",
"name"=>"Materials",
"resource"=>"elements"}},
{"html"=>false,
"text"=>"Item Type Lesson Plan Text",
"element_set"=>
{"id"=>3,
"url"=>"http://localhost/omeka-2.1-rc1/api/element_sets/3",
"name"=>"Item Type Metadata",
"resource"=>"element_sets"},
"element"=>
{"id"=>27,
"url"=>"http://localhost/omeka-2.1-rc1/api/elements/27",
"name"=>"Lesson Plan Text",
"resource"=>"elements"}}],
"extended_resources"=>[]}