Skip to content

Improve json conversion with tests and support for older Rails 3.x#787

Closed
cheremukhin23 wants to merge 10 commits intoshakacode:masterfrom
cheremukhin23:improve-json-safe-and-pretty
Closed

Improve json conversion with tests and support for older Rails 3.x#787
cheremukhin23 wants to merge 10 commits intoshakacode:masterfrom
cheremukhin23:improve-json-safe-and-pretty

Conversation

@cheremukhin23
Copy link
Copy Markdown
Contributor

@cheremukhin23 cheremukhin23 commented Mar 31, 2017

  • Add error handling when unable to parse json
  • Add tests to ensure json_safe_and_pretty handles hashes and strings

This change is Reviewable

@coveralls
Copy link
Copy Markdown

coveralls commented Mar 31, 2017

Coverage Status

Coverage increased (+0.003%) to 97.925% when pulling 5867246 on cheremukhin23:improve-json-safe-and-pretty into 5954e36 on shakacode:master.

@coveralls
Copy link
Copy Markdown

coveralls commented Apr 1, 2017

Coverage Status

Coverage increased (+0.01%) to 97.935% when pulling a3ef532 on cheremukhin23:improve-json-safe-and-pretty into 5954e36 on shakacode:master.

@justin808
Copy link
Copy Markdown
Member

Looking great!


Reviewed 1 of 2 files at r1, 1 of 1 files at r2.
Review status: all files reviewed at latest revision, 4 unresolved discussions.


app/helpers/react_on_rails_helper.rb, line 223 at r2 (raw file):

  end

  def json_safe_and_pretty(hash_or_string)

Can we throw here if the value passed is not a hash or a string? What else could the value be?


app/helpers/react_on_rails_helper.rb, line 231 at r2 (raw file):

      escape_json(hash_value.to_json)
    end
  rescue JSON::ParserError => e

Can we move this catch block around the JSON.parse above?

we can do something like:

  hash_value = if hash_or_string.is_a?(String) 
                          begin
                              JSON.parse(hash_or_string)
                           rescue JSON::ParserError => e
                               raise e, %(Cannot parse #{hash_or_string} \n Backtrace: #{e.backtrace.join("\n")})
                          else
                              hash_or_string
                          end  

app/helpers/react_on_rails_helper.rb, line 242 at r2 (raw file):

  end

  def old_json_escape(json)

Can you provide a comment with a link on to the github source of this?


spec/dummy/spec/helpers/react_on_rails_helper_spec.rb, line 40 at r2 (raw file):

      expect(escaped_json).to eq(hash_sanitized)
    end
  end

Can we add a couple tests that confirm the exceptions:

  1. non-hash, non-string passed
  2. non parseable string in development mode

Also, we're never testing the part where we check we're in development mode.

I'd try to mock/stub out the Rails.env for that test.

# RSpec version
it 'tests my code' do
  allow(Rails).to receive(:env).and_return(ActiveSupport::StringInquirer.new('development'))
  # test code
end

Some options from Google


Comments from Reviewable

@justin808
Copy link
Copy Markdown
Member

See note below. I might just release a temp patch on this.


Review status: all files reviewed at latest revision, 5 unresolved discussions.


app/helpers/react_on_rails_helper.rb, line 224 at r2 (raw file):

  def json_safe_and_pretty(hash_or_string)
    hash_value = hash_or_string.is_a?(String) ? JSON.parse(hash_or_string) : hash_or_string

djudji [1:57 AM]
OK, so this is the thing, the code brakes at AppointmentsList component, after the update. It gives an appointments.map is not a function error, which means that it can not iterate over the Object type (edited)

[1:59]
@justin any recommendations?

djudji [3:31 AM]
could it be a new way of passing data from Rails to React (as I am testing more and more, it looks like props is not getting the right values from a controller)?

djudji [3:53 AM]
it hangs inside function render(el, railsContext) in clientStartup.js

[3:55]
this is how I am sending the data to a React component
react_component 'Appointments', props: {appointments: @appointments}

[3:56]
and on "the other side" I get
Object {appointments: "#<Appointment::ActiveRecord_Relation:0x007f972440cb90>"}
instead of an array of Objects, like before updating to 6.9.1 (edited)

justin [8:16 AM]
Dev or production. Please try both.

djudji [9:49 AM]
Currently on dev. Will try it in production again (first app didn't work because I haven't set a new version for react_on_rails in package.json)

OK, this is a bit strange.

  1. I cloned non-updated app
  2. I did upgrade to react_on_rails 6.9.1
  3. Created a new heroku app and pushed the upgraded app to Heroku.

Now everything is working fine in production, but in dev I still have the same error.

This is the URL -> https://calendar-react-on-rails.herokuapp.com/

I can confirm that both of the apps work when pushed to production.

This is the first URL -> https://calendar-railsreact.herokuapp.com/ (edited

the error is in the conversion to the pretty JSON… for development mode.

   if Rails.env.development?
     # TODO: for json_safe_and_pretty
     # 1. Add test
     # 2. Add error handler if cannot parse the string with nice message
     # 3. Consider checking that if not a string then a Hash
     hash_value = hash_or_string.is_a?(String) ? JSON.parse(hash_or_string) : hash_or_string
     ERB::Util.json_escape(JSON.pretty_generate(hash_value))
   else
     ERB::Util.json_escape(hash_or_string.to_json)
   end
 end

Before, we used to call:

    props.is_a?(String) ? json_escape(props) : props.to_json
  end```


So I think if a Hash is passed, rather than a string, and we want to pretty print, then we’d have to go:

1. Hash => to_json (converts active record objects) => String
2. String => Hash
3. Then call `ERB::Util.json_escape(JSON.pretty_generate(hash_value))`

This could be a little slow.

1. Wondering if this should be optional, in `config/initializers/react_on_rails.rb`
2. Another option is skip pretty printing completely (but then should make an option).

---


*Comments from [Reviewable](https://reviewable.io:443/reviews/shakacode/react_on_rails/787#-:-KggFA9_7z0FTL11MGXB:b-u1x6lu)*
<!-- Sent from Reviewable.io -->

@justin808
Copy link
Copy Markdown
Member

Note #789 is removing the pretty formatting.

We can add it back in...

@justin808
Copy link
Copy Markdown
Member

@cheremukhin23 I thought more about the pretty formatting of json.

Let's add a configuration flag for this, since it tends to break...

Default is false.

# Pretty printing props looks nice when you view the page source. However, if you have a large
# amount of props data, the page rendering can be a little slower.
config.pretty_print_props_in_development = false

@justin808
Copy link
Copy Markdown
Member

See #791. I fixed another critical bug...

[1] (pry) #<#<Class:0x007f84e5bd19f8>>: 0> puts hash_or_string.to_json
"{\"comments\":[{\"id\":9,\"author\":\"xxx\",\"text\":\"xxxxxx\",\"created_at\":\"2017-01-11T08:14:10.296Z\",\"updated_at\":\"2017-01-11T08:14:10.296Z\"},

[2] (pry) #<Class:0x007f84e5bd19f8>>: 0> puts hash_or_string
{"comments":[{"id":9,"author":"xxx","text":"xxxxxx","created_at":"2017-01-11T08:14:10.296Z","updated_at":"2017-01-11T08:14:10.296Z"},

@justin808
Copy link
Copy Markdown
Member

See #799

@cheremukhin23
Copy link
Copy Markdown
Contributor Author

Review status: 0 of 2 files reviewed at latest revision, 5 unresolved discussions.


app/helpers/react_on_rails_helper.rb, line 223 at r2 (raw file):

Previously, justin808 (Justin Gordon) wrote…

Can we throw here if the value passed is not a hash or a string? What else could the value be?

We discard this code


app/helpers/react_on_rails_helper.rb, line 224 at r2 (raw file):

Previously, justin808 (Justin Gordon) wrote…

djudji [1:57 AM]
OK, so this is the thing, the code brakes at AppointmentsList component, after the update. It gives an appointments.map is not a function error, which means that it can not iterate over the Object type (edited)

[1:59]
@justin any recommendations?

djudji [3:31 AM]
could it be a new way of passing data from Rails to React (as I am testing more and more, it looks like props is not getting the right values from a controller)?

djudji [3:53 AM]
it hangs inside function render(el, railsContext) in clientStartup.js

[3:55]
this is how I am sending the data to a React component
react_component 'Appointments', props: {appointments: @appointments}

[3:56]
and on "the other side" I get
Object {appointments: "#<Appointment::ActiveRecord_Relation:0x007f972440cb90>"}
instead of an array of Objects, like before updating to 6.9.1 (edited)

justin [8:16 AM]
Dev or production. Please try both.

djudji [9:49 AM]
Currently on dev. Will try it in production again (first app didn't work because I haven't set a new version for react_on_rails in package.json)

OK, this is a bit strange.

  1. I cloned non-updated app
  2. I did upgrade to react_on_rails 6.9.1
  3. Created a new heroku app and pushed the upgraded app to Heroku.

Now everything is working fine in production, but in dev I still have the same error.

This is the URL -> https://calendar-react-on-rails.herokuapp.com/

I can confirm that both of the apps work when pushed to production.

This is the first URL -> https://calendar-railsreact.herokuapp.com/ (edited

the error is in the conversion to the pretty JSON… for development mode.

   if Rails.env.development?
     # TODO: for json_safe_and_pretty
     # 1. Add test
     # 2. Add error handler if cannot parse the string with nice message
     # 3. Consider checking that if not a string then a Hash
     hash_value = hash_or_string.is_a?(String) ? JSON.parse(hash_or_string) : hash_or_string
     ERB::Util.json_escape(JSON.pretty_generate(hash_value))
   else
     ERB::Util.json_escape(hash_or_string.to_json)
   end
 end

Before, we used to call:

    props.is_a?(String) ? json_escape(props) : props.to_json
  end```


So I think if a Hash is passed, rather than a string, and we want to pretty print, then we’d have to go:

1. Hash => to_json (converts active record objects) => String
2. String => Hash
3. Then call `ERB::Util.json_escape(JSON.pretty_generate(hash_value))`

This could be a little slow.

1. Wondering if this should be optional, in `config/initializers/react_on_rails.rb`
2. Another option is skip pretty printing completely (but then should make an option).
</blockquote></details>

currently decided not to use pretty generate

---

*[app/helpers/react_on_rails_helper.rb, line 231 at r2](https://reviewable.io:443/reviews/shakacode/react_on_rails/787#-KgcggrDdvDqTLt3uR8q:-KhSNfG5p3IgHg_wp0bx:b-vjole3) ([raw file](https://github.com/shakacode/react_on_rails/blob/a3ef532d26039dc87d3032142a3171a6d26b2f3a/app/helpers/react_on_rails_helper.rb#L231)):*
<details><summary><i>Previously, justin808 (Justin Gordon) wrote…</i></summary><blockquote>

Can we move this catch block around the JSON.parse above?

we can do something like:

```ruby
  hash_value = if hash_or_string.is_a?(String) 
                          begin
                              JSON.parse(hash_or_string)
                           rescue JSON::ParserError => e
                               raise e, %(Cannot parse #{hash_or_string} \n Backtrace: #{e.backtrace.join("\n")})
                          else
                              hash_or_string
                          end  

discarded code


app/helpers/react_on_rails_helper.rb, line 242 at r2 (raw file):

Previously, justin808 (Justin Gordon) wrote…

Can you provide a comment with a link on to the github source of this?

added link


spec/dummy/spec/helpers/react_on_rails_helper_spec.rb, line 40 at r2 (raw file):

Previously, justin808 (Justin Gordon) wrote…

Can we add a couple tests that confirm the exceptions:

  1. non-hash, non-string passed
  2. non parseable string in development mode

Also, we're never testing the part where we check we're in development mode.

I'd try to mock/stub out the Rails.env for that test.

# RSpec version
it 'tests my code' do
  allow(Rails).to receive(:env).and_return(ActiveSupport::StringInquirer.new('development'))
  # test code
end

Some options from Google

added test for arguments


Comments from Reviewable

@justin808
Copy link
Copy Markdown
Member

We need to fix this deprecation for React.

====> React On Rails: Checking app/assets/webpack for outdated/missing bundles
You're running an old version of PhantomJS, update to >= 2.1.1 for a better experience.
  the hello world example works (FAILED - 1)
Failures:
  1) Hello World the hello world example works
     Failure/Error: visit "/hello_world"
     
     Capybara::Poltergeist::JavascriptError:
       One or more errors were raised in the Javascript code on the page. If you don't care about these errors, you can ignore them by setting js_errors: false in your Poltergeist configuration (see documentation for details).
     
       Warning: Accessing PropTypes via the main React package is deprecated. Use the prop-types package from npm instead.
       Warning: Accessing PropTypes via the main React package is deprecated. Use the prop-types package from npm instead.
           at :36 in printWarning
     # /home/travis/.rvm/gems/ruby-2.2.6/gems/poltergeist-1.13.0/lib/capybara/poltergeist/browser.rb:376:in `command'
     # /home/travis/.rvm/gems/ruby-2.2.6/gems/poltergeist-1.13.0/lib/capybara/poltergeist/browser.rb:35:in `visit'
     # /home/travis/.rvm/gems/ruby-2.2.6/gems/poltergeist-1.13.0/lib/capybara/poltergeist/driver.rb:97:in `visit'
     # /home/travis/.rvm/gems/ruby-2.2.6/gems/capybara-2.12.1/lib/capybara/session.rb:252:in `visit'
     # /home/travis/.rvm/gems/ruby-2.2.6/gems/capybara-2.12.1/lib/capybara/dsl.rb:52:in `block (2 levels) in <module:DSL>'
     # ./spec/features/hello_world_spec.rb:5:in `block (2 levels) in <top (required)>'
     # /home/travis/.rvm/gems/ruby-2.2.6/gems/rspec-retry-0.5.3/lib/rspec/retry.rb:112:in `block in run'
     # /home/travis/.rvm/gems/ruby-2.2.6/gems/rspec-retry-0.5.3/lib/rspec/retry.rb:101:in `loop'
     # /home/travis/.rvm/gems/ruby-2.2.6/gems/rspec-retry-0.5.3/lib/rspec/retry.rb:101:in `run'
     # /home/travis/.rvm/gems/ruby-2.2.6/gems/rspec-retry-0.5.3/lib/rspec_ext/rspec_ext.rb:12:in `run_with_retry'
     # /home/travis/.rvm/gems/ruby-2.2.6/gems/rspec-retry-0.5.3/lib/rspec/retry.rb:30:in `block (2 levels) in setup'
Finished in 2.4 seconds (files took 2.58 seconds to load)
1 example, 1 failure

@justin808
Copy link
Copy Markdown
Member

Looking good:

  1. Few comments.
  2. Need to pass CI. That could be a separate PR on master
  3. Need a CHANGELOG.md entry.

Reviewed 2 of 2 files at r3.
Review status: all files reviewed at latest revision, 1 unresolved discussion, some commit checks broke.


app/helpers/react_on_rails_helper.rb, line 234 at r3 (raw file):

  def escape_json(json)
    return old_json_escape(json) unless Rails::VERSION::STRING >= "4"

I think this not right. What if the Rails version is "10.0".

Please google for a proper version comparator.

Something like this (you creating the rails_version_less_than

 return old_json_escape(json) if rails_version_less_than(4.0)

Comments from Reviewable

@justin808
Copy link
Copy Markdown
Member

@cheremukhin23 See comment: #799 (comment)

@justin808
Copy link
Copy Markdown
Member

@cheremukhin23 @squadette Maybe I should merge this one and let's add the feature in a new PR?

@justin808
Copy link
Copy Markdown
Member

please rebase on master and that should fix the CI, @cheremukhin23

@justin808 justin808 changed the title Improve json safe and pretty Improve json conversion with tests and support for older Rails 3.x Apr 13, 2017
…into improve-json-safe-and-pretty

# Conflicts:
#	app/helpers/react_on_rails_helper.rb
@coveralls
Copy link
Copy Markdown

Coverage Status

Coverage increased (+0.02%) to 97.997% when pulling 78a1c3c on cheremukhin23:improve-json-safe-and-pretty into d5d579e on shakacode:master.

@justin808
Copy link
Copy Markdown
Member

See #812.

@justin808 justin808 closed this Apr 21, 2017
justin808 pushed a commit that referenced this pull request Apr 23, 2017
…ails older than 4.1 (#812)

* Improve json_safe_and_pretty method to handle parse error
* Add tests to json_safe_and_pretty method
* Add old json escape method for Rails versions less than 4
* Add json safe and pretty argument class test
* Add rails version less than method
* Add tests for json encoding helper methods
* Move rails_version_less_than method into Utils module
* Extract json escaping logic into JsonOutput class
* Remove "or equal" logic from rails_version_less_than util method
* Use monkey patch json escape from Rails 4.2 instead of Rails 4
* Memoize result for static method rails_version_less_than
* Update json escaping method into class methods
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants