From 5592c5bf5ea97d76c303efc24ef2f401dff02d1d Mon Sep 17 00:00:00 2001 From: David Litvak Bruno Date: Thu, 12 Oct 2017 21:02:52 +0200 Subject: [PATCH] Add use_camel_case option (#149) * Add use_camel_case option * Delegate skipping of snake_case to snakify --- CHANGELOG.md | 2 ++ README.md | 5 +++++ lib/contentful/asset.rb | 4 ++-- lib/contentful/base_resource.rb | 6 +++--- lib/contentful/client.rb | 2 ++ lib/contentful/content_type.rb | 2 ++ lib/contentful/entry.rb | 6 ++++-- lib/contentful/fields_resource.rb | 13 ++++++++----- lib/contentful/file.rb | 20 ++++++++++++++------ lib/contentful/support.rb | 5 ++++- spec/asset_spec.rb | 9 +++++++++ spec/content_type_spec.rb | 10 ++++++++++ spec/deleted_asset_spec.rb | 10 ++++++++++ spec/deleted_entry_spec.rb | 10 ++++++++++ spec/entry_spec.rb | 11 +++++++++++ spec/file_spec.rb | 10 ++++++++++ spec/link_spec.rb | 9 +++++++++ 17 files changed, 115 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f22665b..8bd05db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # Change Log ## Unreleased +### Added +* Added `:use_camel_case` option to client. [#142](https://github.com/contentful/contentful.rb/issues/142) ## 2.1.3 ### Fixed diff --git a/README.md b/README.md index 9431fdf..06d1ab8 100644 --- a/README.md +++ b/README.md @@ -251,6 +251,11 @@ tree is allowed to resolved before falling back to `Link` objects). This include on resources with circular dependencies. Defaults to 20. _Note_: If you're using something like `Rails::cache` it's advisable to considerably lower this value (around 5 has proven to be a good compromise - but keep it higher or equal than your maximum API-level include parameter if you need the entire tree resolution). +### :use_camel_case + +When doing the v2 upgrade, all keys and accessors were changed to always use `snake_case`. This option introduces the ability to use `camelCase` for keys and method +accessors. This is very useful for isomorphic applications. + ### Proxy example ```ruby diff --git a/lib/contentful/asset.rb b/lib/contentful/asset.rb index c77ede0..1eff4c1 100644 --- a/lib/contentful/asset.rb +++ b/lib/contentful/asset.rb @@ -73,10 +73,10 @@ def create_files! is_localized = file_json.keys.none? { |f| %w(fileName contentType details url).include? f } if is_localized locales.each do |locale| - @fields[locale][:file] = ::Contentful::File.new(file_json[locale.to_s] || {}) + @fields[locale][:file] = ::Contentful::File.new(file_json[locale.to_s] || {}, @configuration) end else - @fields[internal_resource_locale][:file] = ::Contentful::File.new(file_json) + @fields[internal_resource_locale][:file] = ::Contentful::File.new(file_json, @configuration) end end diff --git a/lib/contentful/base_resource.rb b/lib/contentful/base_resource.rb index 81cf023..2b307f3 100644 --- a/lib/contentful/base_resource.rb +++ b/lib/contentful/base_resource.rb @@ -9,8 +9,8 @@ def initialize(item, configuration = {}, _localized = false, _includes = [], dep @raw = item @default_locale = configuration[:default_locale] @depth = depth - @sys = hydrate_sys @configuration = configuration + @sys = hydrate_sys define_sys_methods! end @@ -69,7 +69,7 @@ def hydrate_sys elsif %w(createdAt updatedAt deletedAt).include?(k) v = DateTime.parse(v) end - result[Support.snakify(k).to_sym] = v + result[Support.snakify(k, @configuration[:use_camel_case]).to_sym] = v end result end @@ -86,7 +86,7 @@ def internal_resource_locale def build_link(item) require_relative 'link' - ::Contentful::Link.new(item) + ::Contentful::Link.new(item, @configuration) end end end diff --git a/lib/contentful/client.rb b/lib/contentful/client.rb index 5237abd..3cfc351 100644 --- a/lib/contentful/client.rb +++ b/lib/contentful/client.rb @@ -36,6 +36,7 @@ class Client max_rate_limit_retries: 1, max_rate_limit_wait: 60, max_include_resolution_depth: 20, + use_camel_case: false, application_name: nil, application_version: nil, integration_name: nil, @@ -70,6 +71,7 @@ def self.get_http(url, query, headers = {}, proxy = {}) # @option given_configuration [Number] :max_rate_limit_retries # @option given_configuration [Number] :max_rate_limit_wait # @option given_configuration [Number] :max_include_resolution_depth + # @option given_configuration [Boolean] :use_camel_case # @option given_configuration [Boolean] :gzip_encoded # @option given_configuration [Boolean] :raw_mode # @option given_configuration [false, ::Logger] :logger diff --git a/lib/contentful/content_type.rb b/lib/contentful/content_type.rb index 5cc35be..4aafb79 100644 --- a/lib/contentful/content_type.rb +++ b/lib/contentful/content_type.rb @@ -22,6 +22,8 @@ def field_for(field_id) fields.detect { |f| Support.snakify(f.id) == Support.snakify(field_id) } end + alias displayField display_field + protected def repr_name diff --git a/lib/contentful/entry.rb b/lib/contentful/entry.rb index 870961f..421ce0c 100644 --- a/lib/contentful/entry.rb +++ b/lib/contentful/entry.rb @@ -16,7 +16,8 @@ def coerce(field_id, value, includes) return build_nested_resource(value, includes) if Support.link?(value) return coerce_link_array(value, includes) if Support.link_array?(value) - content_type = ContentTypeCache.cache_get(sys[:space].id, sys[:content_type].id) + content_type_key = Support.snakify('contentType', @configuration[:use_camel_case]) + content_type = ContentTypeCache.cache_get(sys[:space].id, sys[content_type_key.to_sym].id) unless content_type.nil? content_type_field = content_type.field_for(field_id) @@ -76,7 +77,8 @@ def known_contentful_object?(object) protected def repr_name - "#{super}[#{sys[:content_type].id}]" + content_type_key = Support.snakify('contentType', @configuration[:use_camel_case]).to_sym + "#{super}[#{sys[content_type_key].id}]" end end end diff --git a/lib/contentful/fields_resource.rb b/lib/contentful/fields_resource.rb index 00affe5..2e54737 100644 --- a/lib/contentful/fields_resource.rb +++ b/lib/contentful/fields_resource.rb @@ -65,7 +65,8 @@ def raw_with_links links = fields.keys.select { |property| known_link?(property) } processed_raw = raw.clone raw['fields'].each do |k, v| - processed_raw['fields'][k] = links.include?(Support.snakify(k).to_sym) ? send(Support.snakify(k)) : v + links_key = Support.snakify(k, @configuration[:use_camel_case]) + processed_raw['fields'][k] = links.include?(links_key.to_sym) ? send(links_key) : v end processed_raw @@ -91,8 +92,9 @@ def hydrate_fields(includes) raw['fields'].each do |name, locales| locales.each do |loc, value| result[loc] ||= {} - result[loc][Support.snakify(name).to_sym] = coerce( - Support.snakify(name), + name = Support.snakify(name, @configuration[:use_camel_case]) + result[loc][name.to_sym] = coerce( + name, value, includes ) @@ -100,8 +102,9 @@ def hydrate_fields(includes) end else raw['fields'].each do |name, value| - result[locale][Support.snakify(name).to_sym] = coerce( - Support.snakify(name), + name = Support.snakify(name, @configuration[:use_camel_case]) + result[locale][name.to_sym] = coerce( + name, value, includes ) diff --git a/lib/contentful/file.rb b/lib/contentful/file.rb index 3ab3ae3..c84fbcf 100644 --- a/lib/contentful/file.rb +++ b/lib/contentful/file.rb @@ -1,12 +1,20 @@ module Contentful # An Assets's file info class File - attr_reader :file_name, :content_type, :details, :url - def initialize(json) - @file_name = json.fetch('fileName', nil) - @content_type = json.fetch('contentType', nil) - @details = json.fetch('details', nil) - @url = json.fetch('url', nil) + def initialize(json, configuration) + @configuration = configuration + + define_fields!(json) + end + + private + + def define_fields!(json) + json.each do |k, v| + define_singleton_method Support.snakify(k, @configuration[:use_camel_case]) do + v + end + end end end end diff --git a/lib/contentful/support.rb b/lib/contentful/support.rb index ba98f20..2eddb0c 100644 --- a/lib/contentful/support.rb +++ b/lib/contentful/support.rb @@ -5,9 +5,12 @@ class << self # Transforms CamelCase into snake_case (taken from zucker) # # @param [String] object camelCaseName + # @param [Boolean] skip if true, skips returns original object # # @return [String] snake_case_name - def snakify(object) + def snakify(object, skip = false) + return object if skip + String(object) .gsub(/::/, '/') .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2') diff --git a/spec/asset_spec.rb b/spec/asset_spec.rb index f0ee4f4..79c7b7d 100644 --- a/spec/asset_spec.rb +++ b/spec/asset_spec.rb @@ -156,4 +156,13 @@ } end end + + describe 'camelCase' do + it 'properties now are accessed with camelcase' do + vcr('asset') { + asset = create_client(use_camel_case: true).asset('nyancat') + expect(asset.file.fileName).to eq 'Nyan_cat_250px_frame.png' + } + end + end end diff --git a/spec/content_type_spec.rb b/spec/content_type_spec.rb index 532ccc6..ee2de83 100644 --- a/spec/content_type_spec.rb +++ b/spec/content_type_spec.rb @@ -36,4 +36,14 @@ expect(content_type).to respond_to :display_field end end + + describe 'camel case' do + it 'supports camel case' do + vcr('content_type') { + content_type = create_client(use_camel_case: true).content_type 'cat' + + expect(content_type.displayField).to eq 'name' + } + end + end end diff --git a/spec/deleted_asset_spec.rb b/spec/deleted_asset_spec.rb index 0d174cb..15807bc 100644 --- a/spec/deleted_asset_spec.rb +++ b/spec/deleted_asset_spec.rb @@ -25,4 +25,14 @@ expect(deleted_asset.created_at).to be_a DateTime end end + + describe 'camel case' do + it 'supports camel case' do + vcr('sync_deleted_asset') { + deleted_asset = create_client(use_camel_case: true).sync(initial: true, type: 'DeletedAsset').first_page.items[0] + + expect(deleted_asset.createdAt).to be_a DateTime + } + end + end end diff --git a/spec/deleted_entry_spec.rb b/spec/deleted_entry_spec.rb index b34bf5c..eac4cac 100644 --- a/spec/deleted_entry_spec.rb +++ b/spec/deleted_entry_spec.rb @@ -25,4 +25,14 @@ expect(deleted_entry.created_at).to be_a DateTime end end + + describe 'camel case' do + it 'supports camel case' do + vcr('sync_deleted_entry') { + deleted_entry = create_client(use_camel_case: true).sync(initial: true, type: 'DeletedEntry').first_page.items[0] + + expect(deleted_entry.createdAt).to be_a DateTime + } + end + end end diff --git a/spec/entry_spec.rb b/spec/entry_spec.rb index 55985bf..79891e6 100644 --- a/spec/entry_spec.rb +++ b/spec/entry_spec.rb @@ -358,4 +358,15 @@ def test_dump(nyancat) } end end + + describe 'camel case' do + it 'supports camel case' do + vcr('entry') { + entry = create_client(use_camel_case: true).entry 'nyancat' + + expect(entry.bestFriend.name).to eq 'Happy Cat' + expect(entry.createdAt).to be_a DateTime + } + end + end end diff --git a/spec/file_spec.rb b/spec/file_spec.rb index 882ea78..31cff5b 100644 --- a/spec/file_spec.rb +++ b/spec/file_spec.rb @@ -20,4 +20,14 @@ expect(file.details).to be_instance_of Hash end end + + describe 'camel case' do + it 'supports camel case' do + vcr('asset') { + file = create_client(use_camel_case: true).asset('nyancat').file + expect(file.contentType).to eq 'image/png' + expect(file.fileName).to eq 'Nyan_cat_250px_frame.png' + } + end + end end diff --git a/spec/link_spec.rb b/spec/link_spec.rb index a2e0648..a63051f 100644 --- a/spec/link_spec.rb +++ b/spec/link_spec.rb @@ -38,4 +38,13 @@ end end end + + describe 'camel case' do + it 'supports camel case' do + vcr('entry') { + space_link = create_client(use_camel_case: true).entry('nyancat').space + expect(space_link.linkType).to eq 'Space' + } + end + end end