From 79b64827e2588e84d4cea33541cccda6f28dfdfb Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Tue, 5 Apr 2011 19:38:43 -0700 Subject: [PATCH] Refactor common code out of Page and Form and simplify it --- Manifest.txt | 3 +- lib/mechanize/element_matcher.rb | 35 +++++++++++++++++++++ lib/mechanize/form.rb | 54 +++++++++++--------------------- lib/mechanize/page.rb | 38 ++++++---------------- 4 files changed, 66 insertions(+), 64 deletions(-) create mode 100644 lib/mechanize/element_matcher.rb diff --git a/Manifest.txt b/Manifest.txt index 9ab2899a..cd0c84cb 100644 --- a/Manifest.txt +++ b/Manifest.txt @@ -15,6 +15,7 @@ lib/mechanize.rb lib/mechanize/content_type_error.rb lib/mechanize/cookie.rb lib/mechanize/cookie_jar.rb +lib/mechanize/element_matcher.rb lib/mechanize/file.rb lib/mechanize/file_connection.rb lib/mechanize/file_request.rb @@ -142,6 +143,7 @@ test/test_mechanize_file_response.rb test/test_mechanize_form_image_button.rb test/test_mechanize_page.rb test/test_mechanize_uri_resolver.rb +test/test_mechanize_util.rb test/test_meta.rb test/test_multi_select.rb test/test_no_attributes.rb @@ -167,5 +169,4 @@ test/test_ssl_server.rb test/test_subclass.rb test/test_textarea.rb test/test_upload.rb -test/test_util.rb test/test_verbs.rb diff --git a/lib/mechanize/element_matcher.rb b/lib/mechanize/element_matcher.rb new file mode 100644 index 00000000..6b3c29c3 --- /dev/null +++ b/lib/mechanize/element_matcher.rb @@ -0,0 +1,35 @@ +module Mechanize::ElementMatcher + + def elements_with singular, plural = "#{singular}s" + class_eval <<-CODE + def #{plural}_with criteria = {} + criteria = if String === criteria then + {:name => criteria} + else + criteria.map do |k, v| + k = :dom_id if k.to_sym == :id + [k, v] + end + end + + f = #{plural}.find_all do |thing| + criteria.all? do |k,v| + v === thing.send(k) + end + end + yield f if block_given? + f + end + + def #{singular}_with criteria = {} + f = #{plural}_with(criteria).first + yield f if block_given? + f + end + + alias :#{singular} :#{singular}_with + CODE + end + +end + diff --git a/lib/mechanize/form.rb b/lib/mechanize/form.rb index 7b16423f..624d5ce7 100644 --- a/lib/mechanize/form.rb +++ b/lib/mechanize/form.rb @@ -7,6 +7,7 @@ require 'mechanize/form/multi_select_list' require 'mechanize/form/select_list' require 'mechanize/form/option' +require 'mechanize/element_matcher' class Mechanize # =Synopsis @@ -22,6 +23,9 @@ class Mechanize # form['name'] = 'Aaron' # puts form['name'] class Form + + extend Mechanize::ElementMatcher + attr_accessor :method, :action, :name attr_reader :fields, :buttons, :file_uploads, :radiobuttons, :checkboxes @@ -136,12 +140,14 @@ def []=(field_name, value) end # Treat form fields like accessors. - def method_missing(id,*args) - method = id.to_s.gsub(/=$/, '') + def method_missing(meth, *args) + method = meth.to_s.gsub(/=$/, '') + if field(method) return field(method).value if args.empty? return field(method).value = args[0] end + super end @@ -272,6 +278,8 @@ def delete_field!(field_name) # field.value = 'hello!' # end + elements_with :field + ## # :method: button_with(criteria) # @@ -288,6 +296,8 @@ def delete_field!(field_name) # button.value = 'hello!' # end + elements_with :button + ## # :method: file_upload_with(criteria) # @@ -304,6 +314,8 @@ def delete_field!(field_name) # field.value = 'foo!' # end + elements_with :file_upload + ## # :method: radiobutton_with(criteria) # @@ -320,6 +332,8 @@ def delete_field!(field_name) # field.check # end + elements_with :radiobutton + ## # :method: checkbox_with(criteria) # @@ -336,41 +350,10 @@ def delete_field!(field_name) # field.check # end - # Woo! meta programming time - { :field => :fields, - :button => :buttons, - :file_upload => :file_uploads, - :radiobutton => :radiobuttons, - :checkbox => :checkboxes, - }.each do |singular,plural| - eval(<<-eomethod) - def #{plural}_with criteria = {} - criteria = {:name => criteria} if String === criteria - - criteria = criteria.map do |k, v| - k = :dom_id if k.to_sym == :id - [k, v] - end - - f = #{plural}.find_all do |thing| - criteria.all? do |k,v| - v === thing.send(k) - end - end - yield f if block_given? - f - end - - def #{singular}_with criteria = {} - f = #{plural}_with(criteria).first - yield f if block_given? - f - end - alias :#{singular} :#{singular}_with - eomethod - end + elements_with :checkbox, :checkboxes private + def parse @fields = [] @buttons = [] @@ -478,5 +461,6 @@ def file_to_multipart(file) body end + end end diff --git a/lib/mechanize/page.rb b/lib/mechanize/page.rb index 58471355..336c178d 100644 --- a/lib/mechanize/page.rb +++ b/lib/mechanize/page.rb @@ -20,6 +20,7 @@ class Mechanize # class Page < Mechanize::File extend Forwardable + extend Mechanize::ElementMatcher attr_accessor :mech @@ -127,6 +128,8 @@ def content_type # ... # end + elements_with :form + ## # :method: link_with(criteria) # @@ -143,6 +146,8 @@ def content_type # puts link.href # end + elements_with :link + ## # :method: base_with(criteria) # @@ -159,6 +164,8 @@ def content_type # puts base.href # end + elements_with :base + ## # :method: frame_with(criteria) # @@ -175,6 +182,8 @@ def content_type # p frame.src # end + elements_with :frame + ## # :method: iframe_with(criteria) # @@ -191,34 +200,7 @@ def content_type # p iframe.src # end - # let's meta program! - [:form, :link, :base, :frame, :iframe].each do |type| - eval(<<-eomethod) - def #{type}s_with(criteria) - criteria = {:name => criteria} if String === criteria - - criteria = criteria.map do |k, v| - k = :dom_id if k.to_sym == :id - [k, v] - end - - f = #{type}s.find_all do |thing| - criteria.all? do |k,v| - v === thing.send(k) - end - end - yield f if block_given? - f - end - - def #{type}_with(criteria) - f = #{type}s_with(criteria).first - yield f if block_given? - f - end - alias :#{type} :#{type}_with - eomethod - end + elements_with :iframe ## # Return a list of all link and area tags