omeka_client 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ad08751ec7991ecc76863bf3f80e24e82e5a34f9
4
- data.tar.gz: 65f8d081ee86f044ba6a8da39606a18395da6488
3
+ metadata.gz: 2c418f1c4a8a156799af715c94334dbe596f48b5
4
+ data.tar.gz: 5f3983cbd7613018f0322870882302c7861dd69f
5
5
  SHA512:
6
- metadata.gz: 836c522e5ffe3984195df0b833ca1a8df3a6f18f7f2f04e184759839e846fffac0c6915b378ce56812bdaa044b6efb242fbec99cbb4b77d94c2d85b66fb724c2
7
- data.tar.gz: 877faf52eb48ef0d1cec2765c6c254597c7634c2f13d806602357b8e27abceb0db117e76f524a87288007d79838a488fb1ee5b98019cae93c421fd6fb00b3604
6
+ metadata.gz: 182384179f38915a0159801aceb7245649e48fd3c10bb964f19c8b1c00d267c7278bdc89104b178c868d5aac6434a342374d22a331e954a4bb0d5c00090c4485
7
+ data.tar.gz: 6d1169b72dc03c26d3e683be72403b3ae05d401d2a4d325f4605cb1500cd93a10e912b4dd3ee396523613f615ac3d7f0d534b23212ac3fa1245b2baee46bd4a1
data/README.md CHANGED
@@ -34,21 +34,26 @@ Next, create a client to interact with your Omeka site. You'll need your endpoin
34
34
  You can use the convenience methods for easy access to data. The most useful methods return classes that represent OmekaItems.
35
35
 
36
36
  item = client.omeka_items(1)
37
- item.id
37
+
38
+ Now you can access every piece of information returned by the Omeka API through the `data` variable.
39
+
40
+ item.data.id
38
41
  # => 1
39
- item.public
42
+ item.data.public
40
43
  # => true
41
- item.dublin_core.title
44
+ item.data.added
45
+ # => "2013-07-13T04:47:08+00:00"
46
+
47
+ But since the data you probably want most are the element texts for either the Dublin Core Metadata or the Item Type Metadata, they can be accessed through methods of this type:
48
+
49
+ item.dc_title
42
50
  # => "Questions of the Soul"
43
- item.dublin_core.author
51
+ item.dc_author
44
52
  # => "Hecker, Isaac Thomas, 1819-1888."
45
- item.item_type
46
- # => "book"
47
- item.item_type_metadata.binding
53
+ item.itm_binding
48
54
  # => "cloth"
49
-
50
- item = client.omeka_items
51
- # returns array of OmekaItem instances
55
+ item.itm_signature
56
+ # => "signed by author"
52
57
 
53
58
  There are some helper methods to get other results in other forms:
54
59
 
@@ -62,12 +67,26 @@ There are some helper methods to get other results in other forms:
62
67
  puts items[0]['url']
63
68
  # => http://localhost/omeka/api/items/1
64
69
 
70
+ Once you have an Omeka item, you can update it on the site, create a new item on the site, or delete it from the site.
71
+
72
+ # Create a new item (your local Ruby item will not point to this new item)
73
+ client.post_item(item)
74
+
75
+ # Update an item
76
+ item.dc_title = "Updated via API"
77
+ client.put_item(item)
78
+
79
+ # Delete an item
80
+ client.delete_item(item)
81
+
65
82
  If you want more flexibility about what you're requesting, you can use the lower-level methods.
66
83
 
67
84
  client.get('collections', 1)
68
85
 
69
86
  client.get_hash('collections', 1)
70
87
 
88
+ You can send information to the Omeka site using the low-level methods `client.push`, `client.put`, and `client.delete`. These methods each takes a JSON object.
89
+
71
90
  If you just want a raw REST connection to Omeka, then you can access the underlying instance from the [Rest gem][].
72
91
 
73
92
  client.connection
@@ -78,10 +97,6 @@ You can run the tests by running `rake test`. You'll need to have an Omeka site
78
97
 
79
98
  You can generate the documentation by running `rake yard`.
80
99
 
81
- ## Future plans
82
-
83
- For now the gem only handles GET requests. I'm going to work on making methods that pull information out of Omeka as robust as possible before I deal with POST, PUT, and DELETE. In particular, the class representations of Omeka items are important. Contributions are more than welcome.
84
-
85
100
  ## License
86
101
 
87
102
  This gem is licensed under the [GPLv3][], the same as Omeka.
@@ -1,10 +1,10 @@
1
1
  module OmekaClient
2
2
 
3
- #
3
+ #
4
4
  # A class to create clients that interact with the Omeka API
5
- #
5
+ #
6
6
  # @author Lincoln Mullen
7
- #
7
+ #
8
8
  class Client
9
9
 
10
10
  attr_accessor :endpoint, :api_key, :connection
@@ -33,7 +33,7 @@ module OmekaClient
33
33
  # @param id [Integer] The id of the specific resource to request. Include
34
34
  # an id to get just one item; do not include it to get all the items.
35
35
  # @param query [Hash] Additional query parameters
36
- #
36
+ #
37
37
  # @return [NetHttpPersistentResponseWrapper] A wrapper around the object
38
38
  # @since 0.0.1
39
39
  def get(resource, id = nil, query = {} )
@@ -65,7 +65,7 @@ module OmekaClient
65
65
  # "items", "collections"
66
66
  # @param body [String] A string containing a JSON representation of the body of the item
67
67
  # @param query = {} [Hash] Additional query parameters (optional)
68
- #
68
+ #
69
69
  # @return [NetHttpPersistentResponseWrapper] A wrapper around the object
70
70
  # @since 0.0.3
71
71
  def post(resource, body = nil, query = {} )
@@ -79,7 +79,7 @@ module OmekaClient
79
79
  # "items", "collections"
80
80
  # @param id [Integer] The id number of the Omeka resource to delete
81
81
  # @param query = {} [Hash] Additional query parameters
82
- #
82
+ #
83
83
  # @return [NetHttpPersistentResponseWrapper] A wrapper around the object
84
84
  # @since 0.0.3
85
85
  def delete(resource, id, query = {} )
@@ -105,7 +105,7 @@ module OmekaClient
105
105
  # "items", "collections"
106
106
  # @param id [Integer] The id number of the Omeka resource to update
107
107
  # @param query = {} [Hash] Additional query parameters
108
- #
108
+ #
109
109
  # @return [NetHttpPersistentResponseWrapper] A wrapper around the object
110
110
  # @since 0.0.3
111
111
  def put(resource, id, body, query = {} )
@@ -115,18 +115,18 @@ module OmekaClient
115
115
  self.connection.put(url, :body => body, :params => query)
116
116
  end
117
117
 
118
- # Methods that return classes
118
+ # Methods that use classes
119
119
  # -------------------------------------------------------------------
120
120
 
121
- #
121
+ #
122
122
  # Get an array or a single Omeka item represented as an OmekaItem class
123
123
  # @param id [Integer] The ID of the item to return. No value gets an
124
124
  # array of all the items.
125
- # @param query = {} [Hash] Additional query parameters
125
+ # @param query = {} [Hash] Additional query parameters
126
126
  # @since 0.0.2
127
- #
127
+ #
128
128
  # @return [OmekaItem] An OmekaItem representation of the desired item,
129
- # or an array of OmekaItems
129
+ # or an array of OmekaItems
130
130
  def omeka_items(id = nil, query = {} )
131
131
  response = self.get_hash('items', id = id, query = query)
132
132
  if id.nil?
@@ -140,11 +140,32 @@ module OmekaClient
140
140
  end
141
141
  end
142
142
 
143
+ # Create a new item from an OmekaItem instance
144
+ # @param omeka_item [OmekaItem] An instance of OmekaItem
145
+ # @since 0.0.4
146
+ def post_item(omeka_item)
147
+ self.post("items", omeka_item.data.to_h.to_json)
148
+ end
149
+
150
+ # Update an item using an OmekaItem instance
151
+ # @param omeka_item [OmekaItem] An instance of OmekaItem
152
+ # @since 0.0.4
153
+ def put_item(omeka_item)
154
+ self.put("items", omeka_item.data.id, omeka_item.data.to_h.to_json)
155
+ end
156
+
157
+ # Delete the item represented by an OmekaItem instance
158
+ # @param omeka_item [OmekaItem] An instance of OmekaItem
159
+ # @since 0.0.4
160
+ def delete_item(omeka_item)
161
+ self.delete("items", omeka_item.data.id)
162
+ end
163
+
143
164
  # Convenience methods
144
165
  # -------------------------------------------------------------------
145
166
 
146
167
  # Get the description of the Omeka site
147
- #
168
+ #
148
169
  # @return [Hash] A hash of the description of the Omeka site
149
170
  def site
150
171
  self.get_hash('site')
@@ -159,9 +180,9 @@ module OmekaClient
159
180
  end
160
181
 
161
182
  # Get a list of the Omeka items
162
- #
183
+ #
163
184
  # TODO: Check that items are available in the resources
164
- #
185
+ #
165
186
  # @return [Array] Returns an array of item hashes
166
187
  # @since 0.0.1
167
188
  def items
@@ -169,9 +190,9 @@ module OmekaClient
169
190
  end
170
191
 
171
192
  # Get a list of the Omeka collections
172
- #
193
+ #
173
194
  # TODO: Check that items are available in the resources
174
- #
195
+ #
175
196
  # @return [Array] Returns an array of collection hashes
176
197
  # @since 0.0.1
177
198
  def collections
@@ -1,61 +1,64 @@
1
- require "ostruct"
1
+ require "recursive-open-struct"
2
2
 
3
3
  module OmekaClient
4
4
 
5
- #
5
+ #
6
6
  # A class to represent an item in an Omeka site
7
- #
7
+ #
8
8
  # @author Lincoln Mullen
9
9
  # @since 0.0.2
10
- #
10
+ #
11
11
  class OmekaItem
12
12
 
13
- # Instance variables for each of the main parts of the metadata
14
- attr_accessor :id, :url, :public, :featured, :added, :modified, \
15
- :item_type, :collection, :owner, :files, :tags, :dublin_core, \
16
- :item_type_metadata, :extended_resources
13
+ attr_accessor :data
17
14
 
18
- #
19
- # Parse the data we got from the API into handy methods
15
+ # Parse the data we got from the API into handy methods. All of the data
16
+ # from the JSON returned by the API is available as RecursiveOpenStructs
17
+ # through @data. The Dublin Core and Item Type Metadata fields are also
18
+ # available though special methods of the form dc_title and itm_field.
19
+ #
20
20
  # @param hash [Hash] Uses the hash from OmekaClient::Client::get_hash
21
- #
21
+ #
22
22
  def initialize(hash)
23
+ @data = RecursiveOpenStruct.new(hash, :recurse_over_arrays => true)
23
24
 
24
- # Some of these values have strings. Others return arrays or hashes.
25
- @id = hash['id']
26
- @url = hash['url']
27
- @public = hash['public']
28
- @featured = hash['featured']
29
- @added = hash['added']
30
- @modified = hash['modified']
31
- @item_type = hash['item_type']
32
- @collection = hash['collection']
33
- @owner = hash['owner']
34
- @files = hash['files']
35
- @tags = hash['tags']
36
- @extended_resources = ['extended_resources']
37
-
38
- # OpenStruct.new requires a hash of method names and methods values,
39
- # which we construct here for Dublin Core and for the Item Type
40
- # Metadata. The downside is that we are discarding some data.
41
- # Element names become method names: "Lesson Plan" to "lesson_plan"
42
- dc_metadata = Hash.new
43
- item_metadata = Hash.new
44
- hash['element_texts'].each do |e|
45
- if e['element_set']['name'] == "Dublin Core"
46
- method_name = e['element']['name'].downcase.gsub(/\s/, '_')
47
- dc_metadata[method_name] = e['text']
48
- elsif e['element_set']['name'] == "Item Type Metadata"
49
- method_name = e['element']['name'].downcase.gsub(/\s/, '_')
50
- item_metadata[method_name] = e['text']
25
+ # Step through the element texts separating them into Dublin Core and
26
+ # Item Type Metadata elements. e is the element text hash; i is the
27
+ # index of the element_text in the array of element texts.
28
+ @data.element_texts.each_with_index do |e, i|
29
+ if e.element_set.name == "Dublin Core"
30
+ # Define a reader method that retrieves the data from this element
31
+ # text in @data
32
+ self.class.send(:define_method,
33
+ # The name of the method will have the form "dc_title"
34
+ e.element.name.downcase.gsub(/^/, 'dc_').gsub(/\s/, '_'),
35
+ proc{ @data.element_texts[i].text }
36
+ )
37
+ # Define a setter method that sets the data for this element text in
38
+ # @ data
39
+ self.class.send(:define_method,
40
+ # The name of the method will have the form "dc_title="
41
+ e.element.name.downcase.gsub(/^/, 'dc_').gsub(/\s/, '_').gsub(/$/, '='),
42
+ proc{ |value| @data.element_texts[i].text = value }
43
+ )
44
+ elsif e.element_set.name == "Item Type Metadata"
45
+ # Define a reader method that retrieves the data from this element
46
+ # text in @data
47
+ self.class.send(:define_method,
48
+ # The name of the method will have the form "itm_field"
49
+ e.element.name.downcase.gsub(/^/, 'itm_').gsub(/\s/, '_'),
50
+ proc{ @data.element_texts[i].text }
51
+ )
52
+ # Define a setter method that sets the data for this element text in
53
+ # @ data
54
+ self.class.send(:define_method,
55
+ # The name of the method will have the form "itm_title="
56
+ e.element.name.downcase.gsub(/^/, 'itm_').gsub(/\s/, '_').gsub(/$/, '='),
57
+ proc{ |value| @data.element_texts[i].text = value }
58
+ )
51
59
  end
52
60
  end
53
61
 
54
- # The OpenStruct will provide methods of the style
55
- # item.dublin_core.title
56
- @dublin_core = OpenStruct.new(dc_metadata)
57
- @item_type_metadata = OpenStruct.new(item_metadata)
58
-
59
62
  end
60
63
 
61
64
  end
@@ -1,4 +1,4 @@
1
1
  module OmekaClient
2
2
  # The version number
3
- VERSION = "0.0.3"
3
+ VERSION = "0.0.4"
4
4
  end
@@ -22,6 +22,8 @@ Gem::Specification.new do |spec|
22
22
  spec.add_development_dependency "rake", "~> 10.1.0"
23
23
  spec.add_development_dependency "minitest"
24
24
  spec.add_development_dependency "yard", "~> 0.8.6.2"
25
+ spec.add_development_dependency "pry", "~> 0.9.12.2"
25
26
 
26
27
  spec.add_dependency "rest", "~> 2.6.3"
28
+ spec.add_dependency "recursive-open-struct", "~> 0.4.3"
27
29
  end
@@ -82,7 +82,7 @@ describe OmekaClient::Client do
82
82
  it "must be able to POST an item and then DELETE it" do
83
83
  body = '{"public":true,"featured":false,"element_texts":[{"html":false,"text":"Item Added via API","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"}}]}'
84
84
  client.post("items", body).code.must_equal 201
85
- id = client.omeka_items.last.id
85
+ id = client.omeka_items.last.data.id
86
86
 
87
87
  # We can't make an assertion yet, because of a bug in the rest gem.
88
88
  client.delete("items", id)
@@ -93,12 +93,23 @@ describe OmekaClient::Client do
93
93
  body_updated = '{"featured":true,"element_texts":[{"html":false,"text":"Item Updated via API","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"}}]}'
94
94
  client.post("items", body_original)
95
95
  item_original = client.omeka_items.last
96
- item_original.dublin_core.title.must_equal "Item Added via API"
97
- item_original.featured.must_equal false
98
- client.put("items", item_original.id, body_updated).code.must_equal 200
99
- item_updated = client.omeka_items(item_original.id)
100
- item_updated.dublin_core.title.must_equal "Item Updated via API"
101
- item_updated.featured.must_equal true
96
+ item_original.dc_title.must_equal "Item Added via API"
97
+ item_original.data.featured.must_equal false
98
+ client.put("items", item_original.data.id, body_updated).code.must_equal 200
99
+ item_updated = client.omeka_items(item_original.data.id)
100
+ item_updated.dc_title.must_equal "Item Updated via API"
101
+ item_updated.data.featured.must_equal true
102
+ end
103
+
104
+ it "must be able to post, put, and delete an OmekaItem" do
105
+ item = client.omeka_items(1)
106
+ item.dc_title = "This item has been added via the API"
107
+ client.post_item(item).code.must_equal 201
108
+ new_item = client.omeka_items.last
109
+ new_item.dc_title.must_equal item.dc_title
110
+ new_item.dc_title = "This item has been updated via the API"
111
+ client.put_item(new_item).code.must_equal 200
112
+ client.delete_item(new_item) # can't test response code because of the bug
102
113
  end
103
114
 
104
115
  end
@@ -3,75 +3,82 @@ require "omeka_client"
3
3
 
4
4
  # Set up an test client
5
5
  test_endpoint = "http://localhost/omeka-2.1-rc1/api"
6
- test_api_key = "c56c8f542bc98483b71896523d4faa6321de193b"
6
+ test_api_key = "3b036221e180af46bafa4b5e4a1db30e84e78e89" # contributor
7
7
  client = OmekaClient::Client.new(test_endpoint, test_api_key)
8
- # item_array = client.omeka_items
9
- item_single = client.omeka_items(1)
10
-
8
+ item = client.omeka_items(1)
11
9
 
12
10
  describe OmekaClient::OmekaItem do
13
11
 
14
- it "should have an ID" do
15
- item_single.id.must_equal 1
12
+ it "should represent the JSON data as a RecursiveOpenStruct" do
13
+ item.data.must_be_instance_of RecursiveOpenStruct
16
14
  end
17
15
 
18
- it "should have a URL" do
19
- item_single.url.must_be_instance_of String
16
+ it "should have an ID" do
17
+ item.data.id.must_equal 1
20
18
  end
21
19
 
22
20
  it "should have a URL" do
23
- item_single.url.must_be_instance_of String
21
+ item.data.url.must_be_instance_of String
24
22
  end
25
23
 
26
24
  it "should know whether it's public" do
27
- item_single.public.wont_be_nil
25
+ item.data.public.wont_be_nil
28
26
  end
29
27
 
30
28
  it "should know whether it's featured" do
31
- item_single.featured.wont_be_nil
29
+ item.data.featured.wont_be_nil
32
30
  end
33
31
 
34
32
  it "should have a date added" do
35
- item_single.added.must_be_instance_of String
33
+ item.data.added.must_be_instance_of String
36
34
  end
37
35
 
38
36
  it "should have a date modified" do
39
- item_single.modified.must_be_instance_of String
37
+ item.data.modified.must_be_instance_of String
40
38
  end
41
39
 
42
40
  it "should have an item type" do
43
- item_single.item_type.must_be_instance_of Hash
41
+ item.data.item_type.must_be_instance_of RecursiveOpenStruct
44
42
  end
45
43
 
46
44
  it "should have a collection" do
47
- item_single.collection.must_be_instance_of Hash
45
+ item.data.collection.must_be_instance_of RecursiveOpenStruct
48
46
  end
49
47
 
50
48
  it "should have files" do
51
- item_single.files.must_be_instance_of Hash
49
+ item.data.files.must_be_instance_of RecursiveOpenStruct
52
50
  end
53
51
 
54
52
  it "should have tags" do
55
- item_single.tags.must_be_instance_of Array
53
+ item.data.tags.must_be_instance_of Array
56
54
  end
57
55
 
58
56
  it "should have extended resources" do
59
- item_single.extended_resources.must_be_instance_of Array
57
+ item.data.extended_resources.must_be_instance_of Array
60
58
  end
61
59
 
62
- it "should have the Dublin Core metadata" do
63
- item_single.dublin_core.must_be_instance_of OpenStruct
60
+ it "should have methods for each of the Dublin Core metadata" do
64
61
  dc_fields = [:title, :subject, :contributor, :description, :creator, \
65
62
  :source, :publisher, :date, :rights, :relation, :format, :language, \
66
63
  :type, :identifier, :coverage]
67
64
  dc_fields.each do |field|
68
- item_single.dublin_core.send(field).must_be_instance_of String
65
+ item.send("dc_#{field}").must_be_instance_of String
69
66
  end
70
67
  end
71
68
 
72
69
  it "should have the Item Type metadata" do
73
- item_single.item_type_metadata.must_be_instance_of OpenStruct
74
- # The item type is unpredictable, so it's hard to be more specific
70
+ # We're assuming we know the item type, in this case Lesson Plan
71
+ itm_fields = [:duration, :standards, :objectives, :materials, \
72
+ :lesson_plan_text]
73
+ itm_fields.each do |field|
74
+ item.send("itm_#{field}").must_be_instance_of String
75
+ end
76
+ end
77
+
78
+ it "should be able to set the Dublin Core values and access them" do
79
+ new_title = "My New DC Title"
80
+ item.dc_title = new_title
81
+ item.data.element_texts[0].text.must_equal new_title
75
82
  end
76
83
 
77
84
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: omeka_client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lincoln Mullen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-07-30 00:00:00.000000000 Z
11
+ date: 2013-08-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - ~>
67
67
  - !ruby/object:Gem::Version
68
68
  version: 0.8.6.2
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: 0.9.12.2
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: 0.9.12.2
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: rest
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -80,6 +94,20 @@ dependencies:
80
94
  - - ~>
81
95
  - !ruby/object:Gem::Version
82
96
  version: 2.6.3
97
+ - !ruby/object:Gem::Dependency
98
+ name: recursive-open-struct
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ~>
102
+ - !ruby/object:Gem::Version
103
+ version: 0.4.3
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ~>
109
+ - !ruby/object:Gem::Version
110
+ version: 0.4.3
83
111
  description: A REST client to access the Omeka API
84
112
  email:
85
113
  - lincoln@lincolnmullen.com