Class: Ballonizer
- Inherits:
-
Object
- Object
- Ballonizer
- Defined in:
- lib/ballonizer.rb
Overview
This gem provides mechanisms to allow ballons (or speech bubbles) to be added/removed/edited over images of a HTML or XHTML document and to be persisted. The edition of the ballons is possible by the javascript module provided by this gem. The persistence is allowed by the Ballonizer class. The Ballonizer class is basically a wrapper around the database used to persist the ballons, and offer methods to process the requests made by the client side (by a form created by the javascript module), and to modify a (X)HTML document adding the ballons of the image over it.
This class lacks a lot of features like: access to an abstraction of the ballons, images and their relationship; control over users who edit the ballons; access to the old versions of the ballon set of a image (that are stored in the database, but only can be accessed directly by the Sequel::Database object). It’s a work in progress, be warned to use carefully and motivated to contribute.
The JavaScript library used to allow edition in the client side works as follows: double click over the image add a ballon, double click over a ballon allow edit the text, when the ballon lose the focus it returns to the non-edition state, a ballon without text (or only with spaces) it’s automatically removed when lose focus, drag the ballon change its position (restricted to image space), drag ballon by the right-bottom handle resize the ballon (also restricted to image space). Any change in the ballons make visible a button fixed in the right-top corner of the browser viewport. Every time a ballons is changed (or added/removed) the json of a hidden form is updated. The button submits this json by POST request to the url configured by :form_handler_url setting.
To the image be ‘ballonized’ it have to match the :img_to_ballonize_css_selector. The ‘ballonized’ term here means: have the ballons added over the image in ballonize_page.
To use this class with your (rack isn’t?) app you need to: create the necessary tables in a Sequel::Database object with Ballonizer.create_tables; create a ballonizer instance with the url where you gonna handle the ballon change requests and where provide the assets. Handle the ballon changes request in that url with process_submit. Call instance.ballonize_page over the html documents that can have the images to be ballonized. Check if the image match the css selector :img_to_ballonize_css_selector.
What’s explained above is basically the example you can access with ‘rake example’ and is in the examples/ballonizer_app/config.ru file. You can reset the database with ‘rake db:reset’ (and if you pass an argument as ‘rake db:reset’ you can create the tables in the database already used by your app). The tables names are: images, ballons, ballonized_image_versions, ballonized_image_ballons.
This documentation is avaliable also in: www.omniref.com/ruby/gems/ballonizer
Changelog:
v0.7.3
* Solve the annoying arrow key problem. Stop the propagation of
the key events while editing a balloon. This is meant to solve
the problem with some sites that use the arrow keys to navigate
between pages. If you used one of these keys while editing a
ballon you would lose all work.
v0.7.2
* Little CSS fix (normalize line-height for ballons)
v0.7.1
* Fix the big submit button problem and the hidden behind other
element submit button problem.
v0.7.0
* Add the jquery_no_conflict option. If this option is true the
js_load_snippet will restore any previous loaded version of
jQuery after the ballonizer javascript client code already
referenced the latest loaded version (use this option if the page
already use a jQuery version that's different from the used by
the gem, and you use the add_required_js_libs_for_edition and
add_js_for_edition options).
v0.6.0
* Change the jQuery version provided by the gem to the 1.10.2
v0.5.1:
* js_load_snippet can take a settings arg too. Fixed ballonize_page to
use the :form_handler_url from the settings argument.
v0.5.0:
* The *_html_links methods can take a settings argument.
* Fixed bug where passing a new asset path to the ballonize_page don't
settings parameter change the asset path that it uses.
* Asset path settings now are parsed as real URIs (need to have a
trailing slash if the intent is use as a dir).
* Updated the rspec version used by the gem (fixed deprecation).
v0.4.0:
* Changed the way the Javascript module add containers in the page
to avoid creating invalid HTML4.0.1/XHTML1.1/HTML5 documents.
* Now the ballonize_page takes a mime-type argument to decide if
the page has to be parsed as XML or HTML (trying to be in
conformance with http://www.w3.org/TR/xhtml-media-types/).
* The change in the ballon size now change the font-size of the
ballon text.
* Database schema change, as consequence of the font-size change,
the database now stores the font-size. No migration provided for
databases in the old format, but the font-size field can be null.
The migration only require adding this column with null value to
all records (see the create_tables code).
* Fixed a bug in the Javascript module that give wrong position and
size values to all ballons that aren't edited/added before submmiting
(only if the image wasn't loaded before the javascript loading).
Defined Under Namespace
Classes: Error, SubmitError
Constant Summary collapse
- ASSETS =
The load paths of assets inside the gem and the files inside each path, in the order they need to be included (the files of the first path need to be included before the files in the second path, and the files in the same path need to be included in the specified order). Give preference to the asset(s)_* and *_html_links methods over this constant.
Workaround.deep_freeze([ ['vendor/assets/javascripts', [ 'jquery-1.10.2.min.js', 'jquery.json-2.4.min.js', 'jquery-ui-1.10.3.custom.min.js']], ['lib/assets/javascripts', [ 'ballonizer.js']], ['vendor/assets/stylesheets', [ 'ui-lightness/jquery-ui-1.10.3.custom.min.css']], ['lib/assets/stylesheets', [ 'ballonizer.css']] ])
- DEFAULT_SETTINGS =
The default #settings
{ # The css selector used to define the elements to ballonize. img_to_ballonize_css_selector: 'img.to_ballonize', # A url to be used in the client-side action attribute of the form for # ballon submition. The value will be used in the javascript snippet that # initialize the ballonizer client javascript allowing ballon edition # (and consequently creating the form). form_handler_url: '#', # Define if the javascript code that allow edition will be added to the page. # (this don't refer to the jquery-* libs and the ballonizer.js only the # snippet to execute when the page is ready) add_js_for_edition: true, # A path string to prefix each href of the css stylesheet links generated # by the js_libs_html_links, and, possibly, added by the ballonize_page # object. Example: if you use Ballonizer.assets_app mapped to '/assets' # then use '/assets' here. This is used with the :add_required_css setting. css_asset_path_for_link: nil, # If the ballonize_page method will add or not the html generated by # #css_html_links (require the :css_asset_path_for_link to be defined). add_required_css: false, # A path string to prefix each js source src generated by the # object. Example: if you use Ballonizer.assets_app mapped to '/assets' # then use '/assets' here. This is used with the # :add_required_js_libs_for_edition setting. js_asset_path_for_link: nil, # If the ballonize_page method will add or not the html generated by # #js_libs_html_links (require the :js_asset_path_for_link to be defined). add_required_js_libs_for_edition: false, # If true and the database argument don't have any of the tables used by # the class call create_tables over the database argument. If false or the # database has at leat one of the tables does nothing. create_tables_if_none: false, # Use the jQuery.noConflict to restore any previous loaded version of the # jQuery in a ballonized page. Only works with add_js_for_edition, and # probably only makes sense with add_required_js_libs_for_edition. jquery_no_conflict: false }.freeze.each { | _, v| v.freeze }
Instance Attribute Summary collapse
-
#db ⇒ Object
Returns the value of attribute db.
-
#settings ⇒ Object
Returns the value of attribute settings.
Class Method Summary collapse
-
.asset_absolute_paths ⇒ Array<String>
List of absolute filepaths to the css and js files needed by the client counterpart and provided by the gem.
-
.asset_load_paths ⇒ Array<String>
List of paths (relative to the gem root directory) to the directories with the css and js provided by the gem.
-
.asset_logical_paths ⇒ Array<String>
List of logical paths to the css and js assets.
-
.assets_app ⇒ Sprockets::Environment
A Rack app that provide the gem css and js.
- .create_ballon_node(ballon_data) ⇒ Object
-
.create_tables(db) ⇒ void
Executes the create_table operations over the Sequel::Database argument.
-
.used_tables ⇒ Array<Symbol>
The names (as symbols) of the tables used by instances of the class.
Instance Method Summary collapse
-
#ballonize_page(page, page_url, mime_type, settings = {}) ⇒ String
Wrap each image to ballonize with a container, add its ballons to the container and, possibly, add the css and js libs and snippet for the edition initialization.
-
#css_html_links(settings = {}) ⇒ String, NilClass
The (X)HTML fragment with the link tags that are added to the page by ballonize_page if the :add_required_css setting is true (the default is false).
-
#initialize(db, settings = {}) ⇒ Ballonizer
constructor
Create a new Ballonizer object from a Sequel Database (with the expected tables, that can be created with Ballonizer.create_tables) and a optional hash of settings.
-
#js_libs_html_links(settings = {}) ⇒ String, NilClass
The (X)HTML fragment with the script tags that are added to the page by ballonize_page if the :add_required_js_libs_for_edition setting is true (the default is false).
-
#js_load_snippet(settings = {}) ⇒ String
Return a String with the snippet added to the pages to allow edition in them.
-
#last_ballon_set_of_image(img_src) ⇒ Object
private
Don’t use this method.
-
#process_submit(env, time = nil) ⇒ Ballonizer
Convenience method for process_submit_json, extract the json from the request, validate and pass to the method.
-
#process_submit_hash(submit_hash, time = nil) ⇒ Ballonizer
Behave as process_submit_json except that takes a already parsed json (hash) and don’t check if it’s tainted.
-
#process_submit_json(submit_json, time = nil) ⇒ Ballonizer
Receive a untainted json (assume as validated by #valid_submit_json?) and add it to the database.
-
#valid_submit_hash?(submit_hash, throw_exceptions = false) ⇒ true, false
Act as #valid_submit_json, but over a already parsed json and don’t (un)taint the hash.
-
#valid_submit_json?(submit_json, throw_exceptions = false) ⇒ true, false
Verify if the json is a valid output from the client counterpart.
Constructor Details
#initialize(db, settings = {}) ⇒ Ballonizer
Create a new Ballonizer object from a Sequel Database (with the expected tables, that can be created with Ballonizer.create_tables) and a optional hash of settings.
248 249 250 251 252 253 254 255 256 257 258 |
# File 'lib/ballonizer.rb', line 248 def initialize(db, settings = {}) @settings = DEFAULT_SETTINGS.merge(settings) if db.is_a? String db = Sequel::Database.connect(db) end if @settings[:create_tables_if_none] && ! (self.class.used_tables.any? { | name | db.table_exists? name }) self.class.create_tables(db) end @db = db end |
Instance Attribute Details
#db ⇒ Object
Returns the value of attribute db.
116 117 118 |
# File 'lib/ballonizer.rb', line 116 def db @db end |
#settings ⇒ Object
Returns the value of attribute settings.
116 117 118 |
# File 'lib/ballonizer.rb', line 116 def settings @settings end |
Class Method Details
.asset_absolute_paths ⇒ Array<String>
List of absolute filepaths to the css and js files needed by the client counterpart and provided by the gem. To all who not want to use assets_app.
662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 |
# File 'lib/ballonizer.rb', line 662 def self.asset_absolute_paths return @asset_absolute_paths if @asset_absolute_paths absolute_lib_dir = File.dirname(File.realpath(__FILE__)) ballonizer_gem_root_dir = File.('../', absolute_lib_dir) @asset_absolute_paths = ASSETS.map do | load_path_and_files | relative_load_path, filepaths = *load_path_and_files absolute_load_path = File.(relative_load_path, ballonizer_gem_root_dir) filepaths.map do | filepath | File.(filepath, absolute_load_path) end end @asset_absolute_paths.flatten! @asset_absolute_paths.freeze end |
.asset_load_paths ⇒ Array<String>
List of paths (relative to the gem root directory) to the directories with the css and js provided by the gem.
629 630 631 632 633 634 635 636 637 638 639 640 641 642 |
# File 'lib/ballonizer.rb', line 629 def self.asset_load_paths return @asset_load_paths if @asset_load_paths absolute_lib_dir = File.dirname(File.realpath(__FILE__)) ballonizer_gem_root_dir = File.('../', absolute_lib_dir) @asset_load_paths = ASSETS.map do | load_path_and_files | load_path = load_path_and_files.first File.(load_path, ballonizer_gem_root_dir) end @asset_load_paths.flatten! @asset_load_paths.freeze end |
.asset_logical_paths ⇒ Array<String>
List of logical paths to the css and js assets. The assets_app respond to any requisition to one of these paths.
647 648 649 650 651 652 653 654 655 656 |
# File 'lib/ballonizer.rb', line 647 def self.asset_logical_paths return @asset_logical_paths if @asset_logical_paths @asset_logical_paths = ASSETS.map do | load_path_and_files | load_path_and_files.last end @asset_logical_paths.flatten! @asset_logical_paths.freeze end |
.assets_app ⇒ Sprockets::Environment
A Rack app that provide the gem css and js. Each call to this method return a new object (clone). The Sprockets::Environment isn’t frozen because it can’t be used with ‘run’ in a rack app if frozen.
686 687 688 689 690 691 692 693 694 |
# File 'lib/ballonizer.rb', line 686 def self.assets_app # dont freeze because run don't work in a frozen sprockets env return @assets_app.clone if @assets_app @assets_app = Sprockets::Environment.new asset_load_paths.each do | load_path | @assets_app.prepend_path load_path end @assets_app.clone end |
.create_ballon_node(ballon_data) ⇒ Object
486 487 488 489 490 491 492 493 494 495 496 497 |
# File 'lib/ballonizer.rb', line 486 def self.create_ballon_node(ballon_data) text = HTMLEntities.new.encode(ballon_data[:text]) style = '' [:top, :left, :width, :height].each do | sym | # transform ratio [0,1] to percent [0, 100] style = style + "#{sym}: #{(ballon_data[sym] * 100)}%;" end style = style + "font-size: #{ballon_data[:font_size]}px;" "<span class='ballonizer_ballon' style='#{style}'>#{text}</span>" end |
.create_tables(db) ⇒ void
This method returns an undefined value.
Executes the create_table operations over the Sequel::Database argument.
547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 |
# File 'lib/ballonizer.rb', line 547 def self.create_tables(db) db.create_table(:images) do primary_key :id String :img_src, :size => 255, :unique => true, :allow_null => false end db.create_table(:ballons) do primary_key :id String :text, :size => 255, :allow_null => false Float :top, :allow_null => false Float :left, :allow_null => false Float :width, :allow_null => false Float :height, :allow_null => false # the font_size allow null to support databases migrated from old versions # (that don't have this field) Float :font_size, :allow_null => true end db.create_table(:ballonized_image_versions) do Integer :version foreign_key :image_id, :images DateTime :time, :allow_null => false primary_key [:version, :image_id] end db.create_table(:ballonized_image_ballons) do Integer :version foreign_key :image_id, :images foreign_key :ballon_id, :ballons foreign_key [:version, :image_id], :ballonized_image_versions end end |
.used_tables ⇒ Array<Symbol>
The names (as symbols) of the tables used by instances of the class.
232 233 234 |
# File 'lib/ballonizer.rb', line 232 def self.used_tables USED_TABLES end |
Instance Method Details
#ballonize_page(page, page_url, mime_type, settings = {}) ⇒ String
Wrap each image to ballonize with a container, add its ballons to the container and, possibly, add the css and js libs and snippet for the edition initialization. Don’t make any change if the page has no images to ballonize. If the page can’t be parsed (as HTML or X(HT)ML, depending of the mime-type) return the page argument without throwing any exceptions. Throw an exception if the mime-type doesn’t match with html or xhtml.
443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 |
# File 'lib/ballonizer.rb', line 443 def ballonize_page(page, page_url, mime_type, settings = {}) settings = @settings.merge(settings) # can raise Ballonizer::Error if the mime-type is invalid parsed_page = Workaround.parse_html_or_xhtml(page, mime_type) # if can't parse return the page unaltered if parsed_page.nil? return page end selector = settings[:img_to_ballonize_css_selector] imgs = parsed_page.css(selector) unless imgs.empty? imgs.wrap('<span class="ballonizer_image_container" ></span>') imgs.each do | img | img_src = img['src'] absolute_normal_src = Addressable::URI.parse(page_url) .join(img_src) .normalize.to_s ballons = last_ballon_set_of_image(absolute_normal_src) ballons.each do | ballon | img.add_previous_sibling(self.class.create_ballon_node(ballon)) end end head = parsed_page.at_css('head') if settings[:add_required_css] head.children.last.add_next_sibling(css_html_links(settings)) end if settings[:add_required_js_libs_for_edition] head.children.last.add_next_sibling(js_libs_html_links(settings)) end if settings[:add_js_for_edition] head.children.last.add_next_sibling(js_load_snippet(settings)) end end parsed_page.to_s end |
#css_html_links(settings = {}) ⇒ String, NilClass
The (X)HTML fragment with the link tags that are added to the page by ballonize_page if the :add_required_css setting is true (the default is false).
585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 |
# File 'lib/ballonizer.rb', line 585 def css_html_links(settings = {}) settings = @settings.merge(settings) return nil unless settings[:css_asset_path_for_link] link_template = '<link rel="stylesheet" type="text/css" href="PATH" />' css_paths = self.class.asset_logical_paths.select do | p | /^.+\.css$/.match(p) end links = css_paths.map do | p | p = Workaround.join_uris(settings[:css_asset_path_for_link], p) link_template.sub('PATH', p) end links.join('') end |
#js_libs_html_links(settings = {}) ⇒ String, NilClass
The (X)HTML fragment with the script tags that are added to the page by ballonize_page if the :add_required_js_libs_for_edition setting is true (the default is false).
609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 |
# File 'lib/ballonizer.rb', line 609 def js_libs_html_links(settings = {}) settings = self.settings.merge(settings) return nil unless settings[:js_asset_path_for_link] link_template = '<script type="text/javascript" src="PATH" ></script>' js_libs_paths = self.class.asset_logical_paths.select do | p | /^.+\.js$/.match(p) end links = js_libs_paths.map do | p | p = Workaround.join_uris(settings[:js_asset_path_for_link], p) link_template.sub('PATH', p) end links.join('') end |
#js_load_snippet(settings = {}) ⇒ String
Return a String with the snippet added to the pages to allow edition in them.
525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 |
# File 'lib/ballonizer.rb', line 525 def js_load_snippet(settings = {}) settings = @settings.merge(settings) # We create a reference to the jQuery because the global variable can be # cleaned by the jQuery.noConflict(true), if the jquery_no_conflict # setting is defined <<-EOF <script type="text/javascript"> var jQueryReference = jQuery; jQueryReference(document).ready(function() { Ballonizer('#{settings[:form_handler_url]}', '.ballonizer_image_container', jQueryReference('body'), jQueryReference); }) #{ 'jQuery.noConflict(true); ' if settings[:jquery_no_conflict] } </script> EOF end |
#last_ballon_set_of_image(img_src) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method don’t make distinction between a image in the database without any ballons (removed in the last version, by example) or a image that isn’t in the database (both return a empty array).
Don’t use this method. It is for internal use only.
504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 |
# File 'lib/ballonizer.rb', line 504 def last_ballon_set_of_image(img_src) db_image = self.db[:images].first({img_src: img_src}) if db_image image_id = db_image[:id] version = self.db[:ballonized_image_versions].where({image_id: image_id}) .max(:version) self.db[:ballonized_image_ballons] .join(:ballons, { ballonized_image_ballons__version: version, ballonized_image_ballons__image_id: image_id, ballonized_image_ballons__ballon_id: :ballons__id }).select(:text, :top, :left, :width, :height, :font_size).all else [] end end |
#process_submit(env, time = nil) ⇒ Ballonizer
Convenience method for process_submit_json, extract the json from the request, validate and pass to the method.
266 267 268 269 270 271 |
# File 'lib/ballonizer.rb', line 266 def process_submit(env, time = nil) request = Rack::Request.new(env) submit_json = request['ballonizer_data'] valid_submit_json?(submit_json, true) process_submit_json(submit_json, time) end |
#process_submit_hash(submit_hash, time = nil) ⇒ Ballonizer
Behave as process_submit_json except that takes a already parsed json (hash) and don’t check if it’s tainted.
386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 |
# File 'lib/ballonizer.rb', line 386 def process_submit_hash(submit_hash, time = nil) time = Time.now unless time self.db.transaction do images = self.db[:images] db_ballons = self.db[:ballons] ballonized_image_versions = self.db[:ballonized_image_versions] ballonized_image_ballons = self.db[:ballonized_image_ballons] submit_hash.each do | img_src, ballons | img_src = Addressable::URI.parse(img_src).normalize.to_s db_image = images.first({img_src: img_src}) image_id, version = nil, nil if db_image image_id = db_image[:id] version = ballonized_image_versions.where({image_id: image_id}) .max(:version) + 1 else image_id = images.insert({img_src: img_src}) version = 1 end ballonized_image_versions.insert({ image_id: image_id, version: version, time: time }) ballons.each do | ballon | db_ballon = db_ballons.first(ballon) ballon_id = db_ballon ? db_ballon[:id] : db_ballons.insert(ballon) ballonized_image_ballons.insert({ image_id: image_id, version: version, ballon_id: ballon_id, }) end end end end |
#process_submit_json(submit_json, time = nil) ⇒ Ballonizer
Receive a untainted json (assume as validated by #valid_submit_json?) and add it to the database.
376 377 378 379 |
# File 'lib/ballonizer.rb', line 376 def process_submit_json(submit_json, time = nil) fail SecurityError, 'the input is tainted' if submit_json.tainted? process_submit_hash(JSON.parse(submit_json), time) end |
#valid_submit_hash?(submit_hash, throw_exceptions = false) ⇒ true, false
This is a instance method because, in the future, the validation can depend of instance settings.
Act as #valid_submit_json, but over a already parsed json and don’t (un)taint the hash.
305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 |
# File 'lib/ballonizer.rb', line 305 def valid_submit_hash?(submit_hash, throw_exceptions=false) if submit_hash.empty? fail SubmitError, "the submit request is empty" end submit_hash.each do | img_src, ballons | unless img_src.is_a?(String) # TODO: validate if valid URI? # TODO: define img_src max lenght? fail SubmitError, "the image src is a '#{img_src.class}' and not a String" end unless Addressable::URI.parse(img_src).absolute? fail SubmitError, "the image src ('#{img_src.class}') is not an absolute URI" end unless ballons.is_a?(Array) fail SubmitError, "the image with src '#{img_src}' is key of a " + "'#{ballons.class}' and not a Array" end ballons.each do | ballon | unless ballon["text"].is_a?(String) fail SubmitError, "the ballon text is a '#{ballon.class}' and not" + " a String" end if ballon["text"].empty? fail SubmitError, "the ballon text is empty" end [:top, :left, :width, :height, :font_size].each do | numeric_attr_name | numeric_attr = ballon[numeric_attr_name.to_s] unless numeric_attr.is_a?(Fixnum) || numeric_attr.is_a?(Float) fail SubmitError, "the #{numeric_attr_name} " + "(#{numeric_attr}) isn't a Fixnum or " + "Float (is a '#{numeric_attr.class}')" end end [:top, :left, :width, :height].each do | bound_name | bound = ballon[bound_name.to_s] unless bound >= 0 && bound <= 1 fail SubmitError, "the #{bound_name.to_s} (#{bound.to_s}) isn't" " between 0 and 1 (both inclusive)" end end ballon_end = {} ballon_end[:x] = ballon["left"] + ballon["width"] ballon_end[:y] = ballon["top"] + ballon["height"] [:x, :y].each do | axis | if ballon_end[axis] > 1 side = { x: "right side", y: "bottom" }[axis] fail SubmitError, "the ballon with text #{ballon["text"].to_s} " + "is trespassing the #{side} of the image" end end end end # if pass everything above return true true rescue SubmitError => exception # HACK: "don't use exceptions for flow control", but this is the most DRY # way... if throw_exceptions then raise exception else false end end |
#valid_submit_json?(submit_json, throw_exceptions = false) ⇒ true, false
This is a instance method because, in the future, the validation can depend of instance settings.
Verify if the json is a valid output from the client counterpart. If the argument is valid untaint, otherwise taint (unless it’s frozen). If the second parameter argument is true the method will throw exceptions when the input is invalid.
286 287 288 289 290 291 292 293 294 295 |
# File 'lib/ballonizer.rb', line 286 def valid_submit_json?(submit_json, throw_exceptions=false) parsed_submit = JSON.parse(submit_json) valid_submit_hash?(parsed_submit, true) submit_json.untaint unless submit_json.frozen? true rescue JSON::ParserError, SubmitError => e submit_json.taint unless submit_json.frozen? raise e if throw_exceptions false end |