contentful / contentful-management.rb

Ruby client for the Contentful Content Management API
https://www.contentful.com/developers/documentation/content-management-api/
MIT License
33 stars 32 forks source link

Rich text field validations prevent operations on content type #211

Open MrAlecJohnson opened 4 years ago

MrAlecJohnson commented 4 years ago

Summary If I have a content type, I can normally use the API to add fields to it.

If that content type contains a rich text field with validations, I can no longer use the API to add fields to it. I've found a workaround, but it destroys some validations.

Details I create a content type called test_type, either through the web app or through the API. That content type does not contain a rich text field. I retrieve the content type through the api with:

test_type = env.content_types.find('test_type')

I can now use the API to add a field to that content type, using either of the documented approaches:

test_field = Contentful::Management::Field.new
test_field.id = 'test_field'
test_field.name = 'Test'
test_field.type = 'Text'
test_type.fields.add(test_field)
test_type.save

or

test_type.fields.create(id: 'test_field', name: 'Test', type: 'Text')
test_type.save

This is fine. But if test_type contains a rich text field, I get an error when trying to save the new field back to the content type:

Traceback (most recent call last):
        15: from /Users/alec/Ruby/content_model/bugfix.rb:20:in `<main>'
        14: from /Users/alec/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/contentful-management-2.10.0/lib/contentful/management/resource.rb:78:in `save'
        13: from /Users/alec/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/contentful-management-2.10.0/lib/contentful/management/resource.rb:69:in `update'
        12: from /Users/alec/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/contentful-management-2.10.0/lib/contentful/management/content_type.rb:170:in `query_attributes'
        11: from /Users/alec/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/contentful-management-2.10.0/lib/contentful/management/content_type.rb:158:in `fields_to_nested_properties_hash'
        10: from /Users/alec/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/contentful-management-2.10.0/lib/contentful/management/content_type.rb:158:in `map'
         9: from /Users/alec/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/contentful-management-2.10.0/lib/contentful/management/content_type.rb:159:in `block in fields_to_nested_properties_hash'
         8: from /Users/alec/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/contentful-management-2.10.0/lib/contentful/management/field.rb:32:in `properties_to_hash'
         7: from /Users/alec/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/contentful-management-2.10.0/lib/contentful/management/field.rb:32:in `each_with_object'
         6: from /Users/alec/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/contentful-management-2.10.0/lib/contentful/management/field.rb:32:in `each'
         5: from /Users/alec/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/contentful-management-2.10.0/lib/contentful/management/field.rb:33:in `block in properties_to_hash'
         4: from /Users/alec/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/contentful-management-2.10.0/lib/contentful/management/field.rb:45:in `parse_value'
         3: from /Users/alec/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/contentful-management-2.10.0/lib/contentful/management/field.rb:89:in `validations_to_hash'
         2: from /Users/alec/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/contentful-management-2.10.0/lib/contentful/management/field.rb:89:in `each_with_object'
         1: from /Users/alec/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/contentful-management-2.10.0/lib/contentful/management/field.rb:89:in `each'
/Users/alec/.rbenv/versions/2.6.3/lib/ruby/gems/2.6.0/gems/contentful-management-2.10.0/lib/contentful/management/field.rb:90:in `block in validations_to_hash': undefined method `properties_to_hash' for {:unique=>true}:Hash (NoMethodError)

When I break things down step by step, this goes wrong at the fields.create stage, hitting an error with the rich text field's validations:

#<Contentful::Management::UnprocessableEntity: HTTP status code: 422 Unprocessable Entity
Message: Validation error
Details: 
    * Name: size - Path: '["fields", 1, "validations", 1]' - Value: ''

Before I run fields.create the rich text field's validations are:

:validations=>[#<Contentful::Management::Validation: @properties={:in=>nil, :size=>{"min"=>nil, "max"=>1000}, :range=>nil, :regexp=>nil, :unique=>false, :present=>false, :linkField=>false, :assetFileSize=>nil, :linkContentType=>nil, :linkMimetypeGroup=>nil, :assetImageDimensions=>nil, :enabledNodeTypes=>nil, :enabledMarks=>nil}>, #<Contentful::Management::Validation: @properties={:in=>nil, :size=>nil, :range=>nil, :regexp=>nil, :unique=>false, :present=>false, :linkField=>false, :assetFileSize=>nil, :linkContentType=>nil, :linkMimetypeGroup=>nil, :assetImageDimensions=>nil, :enabledNodeTypes=>nil, :enabledMarks=>nil}>]

This leaves out a lot of the rich text field validations, such as 'accept only specified entry type'. I assume they in some way account for the second item in the validations array - the one that seems to be blank in the API response.

After I run fields.create the validation objects change to hashes:

:validations=>[{:size=>{"min"=>nil, "max"=>1000}}, {}]  

Partial workaround The problem in my example above seems to be connected to the second item in the validations array - the one that becomes an empty hash during the fields.create process.

So I can avoid these errors by deleting the last item from the rich text field's validations array before I run fields.create. This lets me create and save the new field, no matter what combination of validations I have on my rich text field.

However, it can also delete some validations from the rich text field, so it isn't an ideal workaround! It lets me keep 'required field' (which isn't part of the validations array) and 'limit character count', but if I have any other validations (such as 'accept only specified entry type'), they're deleted. These validation types are the ones that aren't returned by the API, so I'm guessing this is connected to the problem.

An exception This error still happens if the rich text field has no validations. However, it doesn't happen if, when I create the rich text field, I press 'create' without clicking on 'create and configure' or visiting the rich text field's settings menu.

System and environment details I'm running this as a little local testing script in Ruby 2.6.3, using just the Contentful management gem.

vitscurtu commented 4 years ago

Hi all, I have a similar issue. I went into the code and tried to debug it, here's what I've found.

contentful-management-2.12.1/lib/contentful/management/field.rb:90

It crashes when validation is a hash since it does not have properties_to_hash

NoMethodError: undefined method 'properties_to_hash' for {}:Hash

I tried adding a check for hashes, but after trying, the API actually ignored creating a new field

def validations_to_hash(validations)
        validations.each_with_object([]) do |validation, results|
          if validation.is_a? Hash
            results << validation
          else
            results << validation.properties_to_hash
          end
        end
      end
rubydog commented 3 years ago

Hi @MrAlecJohnson and @vitscurtu,

I am taking a look at this issue, and trying to reproduce it. Can you please confirm if you are still facing the issue?

Cheers, Bhushan

MrAlecJohnson commented 3 years ago

Hi @rubydog - thanks for the reply. I've moved on from that job so I'm afraid I don't know how things have changed since this came up. I've pointed folks still working there in the direction of this issue, so hopefully someone will be in touch if it is still causing problems.

vitscurtu commented 3 years ago

@rubydog,

I'm still able to reproduce the issue. Let me know if you need more details/log data.

rubydog commented 2 years ago

@vitscurtu.

Can you please share with me detailed steps to reproduce this issue?