aliyun-oss-ex 0.7.0.1402831795

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. checksums.yaml +7 -0
  2. data/COPYING +19 -0
  3. data/INSTALL +35 -0
  4. data/README +443 -0
  5. data/Rakefile +334 -0
  6. data/bin/oss +6 -0
  7. data/bin/setup.rb +11 -0
  8. data/lib/aliyun/oss.rb +55 -0
  9. data/lib/aliyun/oss/acl.rb +132 -0
  10. data/lib/aliyun/oss/authentication.rb +222 -0
  11. data/lib/aliyun/oss/base.rb +241 -0
  12. data/lib/aliyun/oss/bucket.rb +320 -0
  13. data/lib/aliyun/oss/connection.rb +279 -0
  14. data/lib/aliyun/oss/error.rb +70 -0
  15. data/lib/aliyun/oss/exceptions.rb +134 -0
  16. data/lib/aliyun/oss/extensions.rb +405 -0
  17. data/lib/aliyun/oss/logging.rb +304 -0
  18. data/lib/aliyun/oss/object.rb +612 -0
  19. data/lib/aliyun/oss/owner.rb +45 -0
  20. data/lib/aliyun/oss/parsing.rb +100 -0
  21. data/lib/aliyun/oss/response.rb +181 -0
  22. data/lib/aliyun/oss/service.rb +52 -0
  23. data/lib/aliyun/oss/version.rb +14 -0
  24. data/support/faster-xml-simple/lib/faster_xml_simple.rb +188 -0
  25. data/support/faster-xml-simple/test/regression_test.rb +48 -0
  26. data/support/faster-xml-simple/test/test_helper.rb +18 -0
  27. data/support/faster-xml-simple/test/xml_simple_comparison_test.rb +47 -0
  28. data/support/rdoc/code_info.rb +212 -0
  29. data/test/acl_test.rb +70 -0
  30. data/test/authentication_test.rb +114 -0
  31. data/test/base_test.rb +137 -0
  32. data/test/bucket_test.rb +75 -0
  33. data/test/connection_test.rb +218 -0
  34. data/test/error_test.rb +71 -0
  35. data/test/extensions_test.rb +346 -0
  36. data/test/fixtures.rb +90 -0
  37. data/test/fixtures/buckets.yml +133 -0
  38. data/test/fixtures/errors.yml +34 -0
  39. data/test/fixtures/headers.yml +3 -0
  40. data/test/fixtures/logging.yml +15 -0
  41. data/test/fixtures/loglines.yml +5 -0
  42. data/test/fixtures/logs.yml +7 -0
  43. data/test/fixtures/policies.yml +16 -0
  44. data/test/logging_test.rb +90 -0
  45. data/test/mocks/fake_response.rb +27 -0
  46. data/test/object_test.rb +221 -0
  47. data/test/parsing_test.rb +67 -0
  48. data/test/remote/acl_test.rb +28 -0
  49. data/test/remote/bucket_test.rb +147 -0
  50. data/test/remote/logging_test.rb +86 -0
  51. data/test/remote/object_test.rb +350 -0
  52. data/test/remote/test_file.data +0 -0
  53. data/test/remote/test_helper.rb +34 -0
  54. data/test/response_test.rb +69 -0
  55. data/test/service_test.rb +24 -0
  56. data/test/test_helper.rb +110 -0
  57. metadata +177 -0
@@ -0,0 +1,334 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/testtask'
4
+ require 'rdoc/task'
5
+ require 'rake/packagetask'
6
+ require 'rubygems/package_task'
7
+
8
+ require File.dirname(__FILE__) + '/lib/aliyun/oss'
9
+
10
+ def library_root
11
+ File.dirname(__FILE__)
12
+ end
13
+
14
+ task :default => :test
15
+
16
+ Rake::TestTask.new do |test|
17
+ test.pattern = 'test/*_test.rb'
18
+ test.verbose = true
19
+ end
20
+
21
+ namespace :doc do
22
+ Rake::RDocTask.new do |rdoc|
23
+ rdoc.rdoc_dir = 'doc'
24
+ rdoc.title = "Aliyun::OSS -- Support for Aliyun OSS's REST api"
25
+ rdoc.options << '--line-numbers' << '--inline-source'
26
+ rdoc.rdoc_files.include('README')
27
+ rdoc.rdoc_files.include('COPYING')
28
+ rdoc.rdoc_files.include('INSTALL')
29
+ rdoc.rdoc_files.include('lib/**/*.rb')
30
+ end
31
+
32
+ task :rdoc => 'doc:readme'
33
+
34
+ task :refresh => :rerdoc do
35
+ system 'open doc/index.html'
36
+ end
37
+
38
+ task :readme do
39
+ require File.dirname(__FILE__) + '/support/rdoc/code_info'
40
+ RDoc::CodeInfo.parse('lib/**/*.rb')
41
+
42
+ strip_comments = lambda {|comment| comment.gsub(/^# ?/, '')}
43
+ docs_for = lambda do |location|
44
+ info = RDoc::CodeInfo.for(location)
45
+ raise RuntimeError, "Couldn't find documentation for `#{location}'" unless info
46
+ strip_comments[info.comment]
47
+ end
48
+
49
+ open('README', 'w') do |file|
50
+ file.write ERB.new(IO.read('README.erb')).result(binding)
51
+ end
52
+ end
53
+
54
+ task :deploy => :rerdoc do
55
+ sh %(scp -r doc marcel@rubyforge.org:/var/www/gforge-projects/aliyun/)
56
+ end
57
+ end
58
+
59
+ namespace :dist do
60
+ spec = Gem::Specification.new do |s|
61
+ s.name = 'aliyun-oss-ex'
62
+ s.version = Gem::Version.new(Aliyun::OSS::Version)
63
+ s.summary = "Client library for Aliyun's Open Storage Service's REST API"
64
+ s.description = s.summary
65
+ s.email = 'fanzc.daily@gmail.com'
66
+ s.author = 'steve'
67
+ s.has_rdoc = true
68
+ s.extra_rdoc_files = %w(README COPYING INSTALL)
69
+ s.homepage = 'https://github.com/fanzc/aliyun-oss-sdk-for-ruby'
70
+ s.files = FileList['Rakefile', 'lib/**/*.rb', 'bin/*', 'support/**/*.rb']
71
+ s.executables << 'oss'
72
+ s.test_files = Dir['test/**/*']
73
+
74
+ s.add_dependency 'xml-simple'
75
+ s.add_dependency 'builder'
76
+ s.add_dependency 'mime-types'
77
+ s.rdoc_options = ['--title', "Aliyun::OSS -- Support for Aliyun OSS's REST api",
78
+ '--main', 'README',
79
+ '--line-numbers', '--inline-source']
80
+ end
81
+
82
+ # Regenerate README before packaging
83
+ #task :package => 'doc:readme' #TODO 暂时不生成文档
84
+ task :package
85
+ Gem::PackageTask.new(spec) do |pkg|
86
+ pkg.need_tar_gz = true
87
+ pkg.package_files.include('{lib,script,test,support}/**/*')
88
+ pkg.package_files.include('README')
89
+ pkg.package_files.include('COPYING')
90
+ pkg.package_files.include('INSTALL')
91
+ pkg.package_files.include('Rakefile')
92
+ end
93
+
94
+ desc 'Install with gems'
95
+ task :install => :repackage do
96
+ sh "gem i pkg/#{spec.name}-#{spec.version}.gem"
97
+ end
98
+
99
+ desc 'Uninstall gem'
100
+ task :uninstall do
101
+ sh "gem uninstall #{spec.name} -x"
102
+ end
103
+
104
+ desc 'Reinstall gem'
105
+ task :reinstall => [:uninstall, :install]
106
+
107
+ task :confirm_release do
108
+ print "Releasing version #{spec.version}. Are you sure you want to proceed? [Yn] "
109
+ abort if STDIN.getc == ?n
110
+ end
111
+
112
+ desc 'Tag release'
113
+ task :tag do
114
+ sh %(git tag -a '#{spec.version}-release' -m 'Tagging #{spec.version} release')
115
+ sh 'git push --tags'
116
+ end
117
+
118
+ desc 'Update changelog to include a release marker'
119
+ task :add_release_marker_to_changelog do
120
+ changelog = IO.read('CHANGELOG')
121
+ changelog.sub!(/^head:/, "#{spec.version}:")
122
+
123
+ open('CHANGELOG', 'w') do |file|
124
+ file.write "head:\n\n#{changelog}"
125
+ end
126
+ end
127
+
128
+ task :commit_changelog do
129
+ sh %(git commit CHANGELOG -m "Bump changelog version marker for release")
130
+ sh 'git push'
131
+ end
132
+
133
+ package_name = lambda {|specification| File.join('pkg', "#{specification.name}-#{specification.version}")}
134
+
135
+ desc 'Push a release to rubyforge'
136
+ task :release => [:confirm_release, :clean, :add_release_marker_to_changelog, :package, :commit_changelog, :tag] do
137
+ require 'rubyforge'
138
+ package = package_name[spec]
139
+
140
+ rubyforge = RubyForge.new.configure
141
+ rubyforge.login
142
+
143
+ user_config = rubyforge.userconfig
144
+ user_config['release_changes'] = YAML.load_file('CHANGELOG')[spec.version.to_s].join("\n")
145
+
146
+ version_already_released = lambda do
147
+ releases = rubyforge.autoconfig['release_ids']
148
+ releases.has_key?(spec.name) && releases[spec.name][spec.version.to_s]
149
+ end
150
+
151
+ abort("Release #{spec.version} already exists!") if version_already_released.call
152
+
153
+ begin
154
+ rubyforge.add_release(spec.rubyforge_project, spec.name, spec.version.to_s, "#{package}.tar.gz", "#{package}.gem")
155
+ puts "Version #{spec.version} released!"
156
+ rescue Exception => exception
157
+ puts 'Release failed!'
158
+ raise
159
+ end
160
+ end
161
+
162
+ desc 'Upload a beta gem'
163
+ task :push_beta_gem => [:clobber_package, :package] do
164
+ beta_gem = package_name[spec]
165
+ #sh %(scp #{beta_gem}.gem marcel@rubyforge.org:/var/www/gforge-projects/aliyun/beta)
166
+ sh %(gem push #{beta_gem}.gem)
167
+ end
168
+
169
+ task :spec do
170
+ puts spec.to_ruby
171
+ end
172
+ end
173
+
174
+ desc 'Check code to test ratio'
175
+ task :stats do
176
+ library_files = FileList["#{library_root}/lib/**/*.rb"]
177
+ test_files = FileList["#{library_root}/test/**/*_test.rb"]
178
+ count_code_lines = Proc.new do |lines|
179
+ lines.inject(0) do |code_lines, line|
180
+ next code_lines if [/^\s*$/, /^\s*#/].any? {|non_code_line| non_code_line === line}
181
+ code_lines + 1
182
+ end
183
+ end
184
+
185
+ count_code_lines_for_files = Proc.new do |files|
186
+ files.inject(0) {|code_lines, file| code_lines + count_code_lines[IO.read(file)]}
187
+ end
188
+
189
+ library_code_lines = count_code_lines_for_files[library_files]
190
+ test_code_lines = count_code_lines_for_files[test_files]
191
+ ratio = Proc.new { sprintf('%.2f', test_code_lines.to_f / library_code_lines)}
192
+
193
+ puts "Code LOC: #{library_code_lines} Test LOC: #{test_code_lines} Code to Test Ratio: 1:#{ratio.call}"
194
+ end
195
+
196
+ namespace :test do
197
+ find_file = lambda do |name|
198
+ file_name = lambda {|path| File.join(path, "#{name}.rb")}
199
+ root = $:.detect do |path|
200
+ File.exist?(file_name[path])
201
+ end
202
+ file_name[root] if root
203
+ end
204
+
205
+ TEST_LOADER = find_file['rake/rake_test_loader']
206
+ multiruby = lambda do |glob|
207
+ system 'multiruby', TEST_LOADER, *Dir.glob(glob)
208
+ end
209
+
210
+ desc 'Check test coverage'
211
+ task :coverage do
212
+ system("rcov -x Library -x support --sort coverage #{File.join(library_root, 'test/*_test.rb')}")
213
+ show_test_coverage_results
214
+ end
215
+
216
+ Rake::TestTask.new(:remote) do |test|
217
+ test.pattern = 'test/remote/*_test.rb'
218
+ test.verbose = true
219
+ end
220
+
221
+ Rake::TestTask.new(:all) do |test|
222
+ test.pattern = 'test/**/*_test.rb'
223
+ test.verbose = true
224
+ end
225
+
226
+ desc 'Check test coverage of full stack remote tests'
227
+ task :full_coverage do
228
+ system("rcov -x Library -x support --sort coverage #{File.join(library_root, 'test/remote/*_test.rb')} #{File.join(library_root, 'test/*_test.rb')}")
229
+ show_test_coverage_results
230
+ end
231
+
232
+ desc 'Run local tests against multiple versions of Ruby'
233
+ task :version_audit do
234
+ multiruby['test/*_test.rb']
235
+ end
236
+
237
+ namespace :version_audit do
238
+ desc 'Run remote tests against multiple versions of Ruby'
239
+ task :remote do
240
+ multiruby['test/remote/*_test.rb']
241
+ end
242
+
243
+ desc 'Run all tests against multiple versions of Ruby'
244
+ task :all do
245
+ multiruby['test/**/*_test.rb']
246
+ end
247
+ end
248
+
249
+ def show_test_coverage_results
250
+ system("open #{File.join(library_root, 'coverage/index.html')}") if PLATFORM['darwin']
251
+ end
252
+
253
+ desc 'Remove coverage products'
254
+ task :clobber_coverage do
255
+ rm_r 'coverage' rescue nil
256
+ end
257
+ end
258
+
259
+ namespace :todo do
260
+ class << TODOS = IO.read(File.join(library_root, 'TODO'))
261
+ def items
262
+ split("\n").grep(/^\[\s|X\]/)
263
+ end
264
+
265
+ def completed
266
+ find_items_matching(/^\[X\]/)
267
+ end
268
+
269
+ def uncompleted
270
+ find_items_matching(/^\[\s\]/)
271
+ end
272
+
273
+ def find_items_matching(regexp)
274
+ items.grep(regexp).instance_eval do
275
+ def display
276
+ puts map {|item| "* #{item.sub(/^\[[^\]]\]\s/, '')}"}
277
+ end
278
+ self
279
+ end
280
+ end
281
+ end
282
+
283
+ desc 'Completed todo items'
284
+ task :completed do
285
+ TODOS.completed.display
286
+ end
287
+
288
+ desc 'Incomplete todo items'
289
+ task :uncompleted do
290
+ TODOS.uncompleted.display
291
+ end
292
+ end if File.exists?(File.join(library_root, 'TODO'))
293
+
294
+ namespace :site do
295
+ require 'erb'
296
+ require 'rdoc'
297
+
298
+ readme = lambda { IO.read('README')[/^== Getting started\n(.*)/m, 1] }
299
+
300
+ readme_to_html = lambda do
301
+ handler = SM::ToHtml.new
302
+ handler.instance_eval do
303
+ require 'syntax'
304
+ require 'syntax/convertors/html'
305
+ def accept_verbatim(am, fragment)
306
+ syntax = Syntax::Convertors::HTML.for_syntax('ruby')
307
+ @res << %(<div class="ruby">#{syntax.convert(fragment.txt, true)}</div>)
308
+ end
309
+ end
310
+ SM::SimpleMarkup.new.convert(readme.call, handler)
311
+ end
312
+
313
+ desc 'Regenerate the public website page'
314
+ task :build => 'doc:readme' do
315
+ open('site/public/index.html', 'w') do |file|
316
+ erb_data = {}
317
+ erb_data[:readme] = readme_to_html.call
318
+ file.write ERB.new(IO.read('site/index.erb')).result(binding)
319
+ end
320
+ end
321
+
322
+ task :refresh => :build do
323
+ system 'open site/public/index.html'
324
+ end
325
+
326
+ desc 'Update the live website'
327
+ task :deploy => :build do
328
+ site_files = FileList['site/public/*']
329
+ site_files.delete_if {|file| File.directory?(file)}
330
+ sh %(scp #{site_files.join ' '} marcel@rubyforge.org:/var/www/gforge-projects/aliyun/)
331
+ end
332
+ end
333
+
334
+ task :clean => ['dist:clobber_package', 'doc:clobber_rdoc', 'test:clobber_coverage']
data/bin/oss ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ oss_lib = File.dirname(__FILE__) + '/../lib/aliyun/oss'
3
+ setup = File.dirname(__FILE__) + '/setup'
4
+ irb_name = RUBY_PLATFORM =~ /mswin32/ ? 'irb.bat' : 'irb'
5
+
6
+ exec "#{irb_name} -r #{oss_lib} -r #{setup} --simple-prompt"
@@ -0,0 +1,11 @@
1
+ # -*- encoding : utf-8 -*-
2
+ #!/usr/bin/env ruby
3
+ if ENV['OSS_ACCESS_KEY_ID'] && ENV['OSS_SECRET_ACCESS_KEY']
4
+ Aliyun::OSS::Base.establish_connection!(
5
+ :access_key_id => ENV['OSS_ACCESS_KEY_ID'],
6
+ :secret_access_key => ENV['OSS_SECRET_ACCESS_KEY']
7
+ )
8
+ end
9
+
10
+ require File.dirname(__FILE__) + '/../test/fixtures'
11
+ include Aliyun::OSS
@@ -0,0 +1,55 @@
1
+ # -*- encoding : utf-8 -*-
2
+ require 'cgi'
3
+ require 'uri'
4
+ require 'openssl'
5
+ require 'digest/sha1'
6
+ require 'net/https'
7
+ require 'time'
8
+ require 'date'
9
+ require 'open-uri'
10
+
11
+ $:.unshift(File.dirname(__FILE__))
12
+ require 'oss/extensions'
13
+ require_library_or_gem 'builder' unless defined? Builder
14
+ require_library_or_gem 'mime/types', 'mime-types' unless defined? MIME::Types
15
+
16
+ require 'oss/base'
17
+ require 'oss/version'
18
+ require 'oss/parsing'
19
+ require 'oss/acl'
20
+ require 'oss/logging'
21
+ require 'oss/service'
22
+ require 'oss/owner'
23
+ require 'oss/bucket'
24
+ require 'oss/object'
25
+ require 'oss/error'
26
+ require 'oss/exceptions'
27
+ require 'oss/connection'
28
+ require 'oss/authentication'
29
+ require 'oss/response'
30
+
31
+ Aliyun::OSS::Base.class_eval do
32
+ include Aliyun::OSS::Connection::Management
33
+ end
34
+
35
+ Aliyun::OSS::Bucket.class_eval do
36
+ include Aliyun::OSS::Logging::Management
37
+ include Aliyun::OSS::ACL::Bucket
38
+ end
39
+
40
+ require_library_or_gem 'xmlsimple', 'xml-simple' unless defined? XmlSimple
41
+ # If libxml is installed, we use the FasterXmlSimple library, that provides most of the functionality of XmlSimple
42
+ # except it uses the xml/libxml library for xml parsing (rather than REXML). If libxml isn't installed, we just fall back on
43
+ # XmlSimple.
44
+ Aliyun::OSS::Parsing.parser =
45
+ begin
46
+ require_library_or_gem 'xml/libxml'
47
+ # Older version of libxml aren't stable (bus error when requesting attributes that don't exist) so we
48
+ # have to use a version greater than '0.3.8.2'.
49
+ raise LoadError unless XML::Parser::VERSION > '0.3.8.2'
50
+ $:.push(File.join(File.dirname(__FILE__), '..', '..', 'support', 'faster-xml-simple', 'lib'))
51
+ require_library_or_gem 'faster_xml_simple'
52
+ FasterXmlSimple
53
+ rescue LoadError
54
+ XmlSimple
55
+ end
@@ -0,0 +1,132 @@
1
+ # -*- encoding : utf-8 -*-
2
+ module Aliyun
3
+ module OSS
4
+ # By default buckets are private. This means that only the owner has access rights to the bucket and its objects.
5
+ # Objects in that bucket inherit the permission of the bucket unless otherwise specified. When an object is private, the owner can
6
+ # generate a signed url that exposes the object to anyone who has that url. Alternatively, buckets and objects can be given other
7
+ # access levels. Several canned access levels are defined:
8
+ #
9
+ # * <tt>:private</tt> - Owner gets FULL_CONTROL. No one else has any access rights. This is the default.
10
+ # * <tt>:public_read</tt> - Owner gets FULL_CONTROL and the anonymous principal is granted READ access. If this policy is used on an object, it can be read from a browser with no authentication.
11
+ # * <tt>:public_read_write</tt> - Owner gets FULL_CONTROL, the anonymous principal is granted READ and WRITE access. This is a useful policy to apply to a bucket, if you intend for any anonymous user to PUT objects into the bucket.
12
+ #
13
+ # You can set a canned access level when you create a bucket or an object by using the <tt>:access</tt> option:
14
+ #
15
+ # OSSObject.store(
16
+ # 'kiss.jpg',
17
+ # data,
18
+ # 'marcel',
19
+ # :access => :public_read
20
+ # )
21
+ #
22
+ # Since the image we created is publicly readable, we can access it directly from a browser by going to the corresponding bucket name
23
+ # and specifying the object's key without a special authenticated url:
24
+ #
25
+ # http://oss.aliyuncs.com/marcel/kiss.jpg
26
+ #
27
+ module ACL
28
+ # The ACL::Policy class lets you inspect and modify access controls for buckets and objects.
29
+ # A policy is made up of one or more Grants which specify a permission and a Grantee to whom that permission is granted.
30
+ #
31
+ # Buckets and objects are given a default access policy which contains one grant permitting the owner of the bucket or object
32
+ # FULL_CONTROL over its contents. This means they can read the object, write to the object, as well as read and write its
33
+ # policy.
34
+ #
35
+ # The <tt>acl</tt> method for both buckets and objects returns the policy object for that entity:
36
+ #
37
+ # grant = Bucket.acl('some-bucket')
38
+ # grant = Bucket.acl('some-bucket', :public_read)
39
+ #
40
+
41
+ module Bucket
42
+ def self.included(klass) #:nodoc:
43
+ klass.extend(ClassMethods)
44
+ end
45
+
46
+ module ClassMethods
47
+ # The acl method is the single point of entry for reading and writing access control list policies for a given bucket.
48
+ #
49
+ # # Fetch the acl for the 'marcel' bucket
50
+ # policy = Bucket.acl 'marcel'
51
+ #
52
+ # # Modify the policy ...
53
+ # # Bucket.acl 'marcel', :public_read
54
+ def acl(name = nil, access_level = nil)
55
+ path = path(name) << '?acl'
56
+ if access_level
57
+ put(path, {:access => access_level})
58
+ acl(name)
59
+ else
60
+ respond_with(Policy::Response) do
61
+ policy = get(path).policy
62
+ policy.has_key?('access_control_list') && policy['access_control_list']['grant'][0]
63
+ end
64
+ end
65
+ end
66
+ end
67
+
68
+ # The acl method returns and updates the acl for a given bucket.
69
+ #
70
+ # # Fetch a bucket
71
+ # bucket = Bucket.find 'marcel'
72
+ #
73
+ # # view
74
+ # bucket.acl
75
+ #
76
+ # # write
77
+ # bucket.acl(:public_read)
78
+ def acl(reload = false)
79
+ expirable_memoize(reload) do
80
+ self.class.acl(name, reload)
81
+ end
82
+ end
83
+ end
84
+
85
+ class OptionProcessor #:nodoc:
86
+ attr_reader :options
87
+ class << self
88
+ def process!(options)
89
+ new(options).process!
90
+ end
91
+ end
92
+
93
+ def initialize(options)
94
+ options.to_normalized_options!
95
+ @options = options
96
+ @access_level = extract_access_level
97
+ end
98
+
99
+ def process!
100
+ return unless access_level_specified?
101
+ validate!
102
+ options['x-oss-acl'] = access_level
103
+ end
104
+
105
+ private
106
+ def extract_access_level
107
+ options.delete('access') || options.delete('x-oss-acl')
108
+ end
109
+
110
+ def validate!
111
+ raise InvalidAccessControlLevel.new(valid_levels, access_level) unless valid?
112
+ end
113
+
114
+ def valid?
115
+ valid_levels.include?(access_level)
116
+ end
117
+
118
+ def access_level_specified?
119
+ !@access_level.nil?
120
+ end
121
+
122
+ def valid_levels
123
+ %w(private public-read public-read-write)
124
+ end
125
+
126
+ def access_level
127
+ @normalized_access_level ||= @access_level.to_header
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end